Using session.Merge

Session.Merge is perhaps one of the most misunderstood features in NHibernate. In this recipe, we'll show you how to use session.Merge to associate a dirty, detached entity with a new session. This is particularly handy when recovering from StaleObjectStateExceptions.

Getting ready

Follow the Getting ready step in the Save entities to the database recipe in this chapter.

How to do it…

  1. Add a new folder named MergingEntities to the SessionRecipes project.
  2. Add a class named Recipe to the folder:
    using System;
    using NH4CookbookHelpers.Queries;
    using NH4CookbookHelpers.Queries.Model;
    using NHibernate;
    
    namespace SessionRecipes.MergingEntities
    {
      public class Recipe : QueryRecipe
      {
        protected override void Run(ISessionFactory sessionFactory)
        {
          var book = CreateAndSaveBook(sessionFactory);
          book.Name = "Dormice in Action";
          book.Description = "Hibernation of the Hazel Dormouse";
          book.UnitPrice = 0.83M;
          book.ISBN = "0123";
    
          using (var session = sessionFactory.OpenSession())
          {
            using (var tx = session.BeginTransaction())
            {
              var mergedBook = (Book)session.Merge(book);
              tx.Commit();
    
              Console.WriteLine(
                ReferenceEquals(book, mergedBook));
            }
          }
        }
    
        private static Book CreateAndSaveBook(
      ISessionFactory sessionFactory)
        {
          var book = new Book()
          {
            Name = "The book of awesomeness",
            Description = "Pure Awesome",
            UnitPrice = 50.0M,
            ISBN = "3043",
            Author = "Awe Some",
          };
    
          using (var session = sessionFactory.OpenSession())
          {
            using (var tx = session.BeginTransaction())
            {
              session.Save(book);
              tx.Commit();
              session.Evict(book);
            }
          }
          return book;
        }
      }
    }
  3. Run the application and start the MergingEntities recipe. Inspect the query log.

How it works…

In CreateAndSaveBook, we create a book and save it to the database. We commit our transaction, evict the book from session, close the session, and return the book. This sets up our problem. We now have an entity without a session. Changes to this entity are not being tracked. It's just a plain ordinary book object.

We continue to change the book object and now we want to save those changes. NHibernate doesn't know what we've done to this book. It could have been passed through other layers or tiers of a large application. We don't know the session with which it's associated, if any. We may not even know if the book exists in the database.

Session.Merge handles all of this uncertainty for us. If the current session has a book with this ID, data from our book is copied on to the persistent book object in the session and the persistent book object is returned.

If the current session doesn't have a book with this ID, NHibernate loads it from the database. The changes are copied on to the persistent book object that was just loaded in to the session. The persistent book object is returned.

If NHibernate didn't find a book with that ID in the database, it copies data from our book object on to a new persistent book associated with the session and returns the new persistent book object.

The end result of session.Merge is the same. The book it returns is not the same instance we passed it in, but it contains all of our changes and is associated with the current session. When we commit our transaction, those changes are written to the database.

The book we passed in is not associated with the current session.

See also

  • Using session.Refresh
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.39.59