Using session.Merge
使用session.Merge
session.Merge可能是NHibernate中最被误解的特性之一.本节介绍如何使用session.Merge将一个脏的独立的实体和一个新的会话合并. 这在从StaleObjectStateExceptions恢复时特别有用.
准备
使用第一章的Eg.Core和第二章的Configuring NHibernate with App.config来创建一个控制台应用程序.
步骤
1. 在Main方法中添加如下代码:
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. 添加CreateAndSaveBook方法,代码如下:
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; }
原理
在CreateAndSaveBook方法中,新建了一个book并将它保存到了数据库.提交我们的事务,将该book从会话中剔除,关闭会话并将该book返回. 问题来了,现在有个和会话无关的实体,无法检测该实体的变化,她只是一个普通的book对象.
我们修改了该book对象,并且想要保存这些修改.但是NHibernate不知道我们对该book对象的操作. 她已经可以穿过其他层或大型应用程序中的不同层.我们不知道她和哪个会话关联,我们甚至不知道该book在数据库中是否存在.
Session.Merge会为我们处理所有这些不确定性.如果当前的会话中有该ID的book,那么该book的数据就会被复制到会话中的可持久化的book对象,并且可持久化的book对象会被返回.
如果当前会话中没哟该ID的book,NHibernate会从数据库中加载她.这些修改会被复制到刚加载到会话中的可持久化book对象.该可持久化的book对象会被返回.
如果NHibernate在数据库中也找不到该ID的book,NHibernate会将该book的数据复制到一个新的和会话关联的可持久化book对象,并返回这个新的可持久化book对象.
session.Merge的最终结果是相同的.返回的book对象和传入的book对象时不同的实例,但她包含了我们所做的所有修改并且她被关联到了当前会话.提交事务后,这些修改都会被写入数据库.
我们开始传入的book对象和当前会话是不关联的.