NHibernate 3.0 Cookbook第三章,使用session.Merge的翻译.
session.Merge也许是NHibernate最容易被误解的特性之一.这里我会展示怎么使用一个新的Session的session.Merge来关联一个脏的,游离的实体.这个方法可以非常便利的从StaleObjectStateExceptions中恢复.
准备
使用第一章的Eg.Core的model同时使用App.config配置NHibernate,建立一个控制台应用程序.
怎样做
把下面代码添加到你的主方法里.
static void Main(string[] args) { log4net.Config.XmlConfigurator.Configure(); var nhConfig = new Configuration().Configure(); var sessionFactory = nhConfig.BuildSessionFactory(); 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); // Returns false Console.WriteLine(ReferenceEquals(book, mergedBook)); tx.Commit(); } } }
添加一个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(); } } return book; }
原理
在CreateAndSaveBook方法里,我们新建了一个Book对象同时保存到数据库,我们提交了事务,Book对象脱离了Session,关闭Session,和返回这个book对象.这样就建立了我们的问题.现在我们有一个脱离了Session的实体.这个实体的改变不会被跟踪.它只是一个简单的普通的对象.
我们继续改变这个book对象,现在我们想保存这些变化.NHibernate不知道我们对这个book对象做了什么.它可能被传递到应用程序的其它层.即使有的话,我们也不知道它与那个Session有关联.我们甚至不知道这个book对象在数据库是否存在.
Session.Merge为我们处理所有这些不确定性.如果当前的Session有这个ID的book对象,我们的book对象的数据会复制给这个Session的一个持久态的book对象,返回这个持久态book对象.
如果当前的Session没有这个Id的book对象,NHibernate会从数据库中加载它.数据的变化会被复制给刚刚加载的那个持久态对象,返回这个持久态book对象.
如果NHibernate在数据库中没有找到这个ID的book对象,会复制我们book对象的数据给一个与这个Session关联的持久态对象,返回这个新的持久态对象.
session.Merge最后的结果都是相同的.返回的Book与我们传递进去的不是一个实例,但它包含我们所有的变化和它是与当前的Session关联的.当我们提交事务,这些变化会被写到数据库.
我们传入的Book对象与当前Session是没有关联的.