NHibernate 3.0 Cookbook第三章,使用session.Refresh的翻译.
特别是桌面应用程序,可能有必要用不同的Session重新加载实体以反应最近的变化.这里我们会使用session.Refresh去刷新一个实体的数据,就像被两个Session控制一样.
准备
使用第一章的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 sessionA = sessionFactory.OpenSession(); var sessionB = sessionFactory.OpenSession(); Guid productId; Product productA; Product productB; productA = new Product() { Name = "Lawn Chair", Description = "Lime Green, Comfortable", UnitPrice = 10.00M }; using (var tx = sessionA.BeginTransaction()) { Console.WriteLine("Saving product."); productId = (Guid)sessionA.Save(productA); tx.Commit(); } using (var tx = sessionB.BeginTransaction()) { Console.WriteLine("Changing price."); productB = sessionB.Get<Product>(productId); productB.UnitPrice = 15.00M; tx.Commit(); } using (var tx = sessionA.BeginTransaction()) { Console.WriteLine("Price was {0:c}", productA.UnitPrice); sessionA.Refresh(productA); Console.WriteLine("Price is {0:c}", productA.UnitPrice); tx.Commit(); } sessionA.Close(); sessionB.Close(); Console.ReadKey(); }
2.运行程序,你会看到下面输出:
原理
在这个人为的例子里,我们打开两个Session并且同时操作一个实体的两个实例.在SessionA,我们保存一个新建的Product-10美元一张的浅绿色的草坪椅.在SessionB,我们获取同样的草坪椅.现在我们有同一个实体的两个实例.一个与SessionA关联,另一个与SessionB.
我们改变SessionB草坪椅的价格为15美元(productB.UnitPrice = 15.00M).注意我们没有调用任何方法来保存或更新数据库.因为SessionB加载了这张草坪椅(productB),所有会跟踪变化和当Session flushed的话会自动更新数据库.当我们提交事务时,这些都是自动的.这叫自动脏检测(automatic dirty checking).SessionA的草坪椅的价格仍然是10美元.
当我们调用SessionA.Refresh,NHibernate会自动从数据库刷新数据更新Session的草坪椅.现在,SessionA的草坪椅价格显示新的15美元.
There's more...
session.Refresh在桌面应用程序中特别重要,在这里,我们可能会有几个同时运行中的Sessions来处理各种的数据绑定窗体,并且我们需要一个窗体的保存变化会在另一个窗体中马上得到反应以显示相同的实体.
在这种情景,你最好在窗体间建立一些信息发布机制,使得在一个窗体保存一个实体时传播一条"我保存了这个实体"这样的信息到另一个窗体来显示相同的数据.当窗体接收到这样一条信息时,它就可以调用session.Refresh来获取新的数据.