Using session.Merge

session.Merge is perhaps one of the most misunderstood features in NHibernate. In this recipe, I'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

Using our Eg.Core model from Chapter 1 and the Configuring NHibernate with App.config recipe from Chapter 2, set up a console application.

How to do it...

  1. Add the following code to your Main method:
    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();
    
        // Returns false
        ReferenceEquals(book, mergedBook);
    
      }
    }
  2. Add the CreateAndSaveBook method:
    private static Book CreateAndSaveBook(
      ISessionFactory sessionFactory)
    {
      var book = new Book()
      {
        Name = "NHibernate 3.0 Cookbook",
        Description = "Pure Awesome.",
        UnitPrice = 50.0M,
        ISBN = "3043",
        Author = "Jason Dentler",
      };
    
      using (var session = sessionFactory.OpenSession())
      {
        using (var tx = session.BeginTransaction())
        {
          session.Save(book);
          tx.Commit();
          session.Evict(book);
        }
      }
    
      return book;
    }

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 with which session 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 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
18.116.14.245