dragonfly
dragonfly

Reputation: 17773

Difference between ISession.Save/Update and ITransaction.Commit in NHibernate

I have a piece of code that adds elements to entity collection (one-to-many relation). This is the version with ISession.Save

        using (ISession session = sessionFactory.OpenSession())
        {
            var package = session.QueryOver<Package>().Where(x => x.ID == selectedPackage).SingleOrDefault();
            foreach(var themeId in selectedThemes)
            {
                var selectedTheme = session.QueryOver<HBTheme>().Where(x => x.ID == themeId).SingleOrDefault();
                if (selectedTheme != null)
                {
                    package.Themes.Add(new PackageTheme() { Package = package, Theme = selectedTheme });
                }
            }
            session.Save(package);
        }

and that version didn't work for me. As I had test written with ITransaction, I changed it a little to the following:

        using (ISession session = sessionFactory.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            var package = session.QueryOver<Package>().Where(x => x.ID == selectedPackage).SingleOrDefault();
            foreach(var themeId in selectedThemes)
            {
                var selectedTheme = session.QueryOver<HBTheme>().Where(x => x.ID == themeId).SingleOrDefault();
                if (selectedTheme != null)
                {
                    package.Themes.Add(new PackageTheme() { Package = package, Theme = selectedTheme });
                }
            }
            transaction.Commit();
        }

and now it works. Elements in package.Themes collection are stored in database. How come? Thanks!

Upvotes: 2

Views: 1158

Answers (1)

Oskar Berggren
Oskar Berggren

Reputation: 5629

Comparing apples and oranges!

  1. Save() will tell NHibernate that "this object should be made persistent". Exactly when the INSERT statement is emitted is not defined, and may happen some time later.
  2. Save() may be unnecessary depending on the cascade settings.
  3. You should always use a transaction.
  4. Flushing of dirty state to the actual database by default happens on transaction commit and when querying, if the dirty state might affect the outcome of the query.

What happens in case 1 is likely that a flush operation is never triggered. In case 2 the item is probably saved due to cascading on the collection, while the transaction commit triggers the flush.

Upvotes: 7

Related Questions