NHibernate之旅(13):初探立即加载机制

本节内容

引入立即加载实例分析1.一对多关系实例2.多对多关系实例结语引入

通过上一篇的介绍,我们知道了NHibernate中默认的加载机制——延迟加载。其本质就是使用GoF23中代理模式实现,这节我们简单分析NHibernate另一种加载机制——立即加载。我用一张图片形象的展现立即加载机制。

立即加载

顾名思义,就是立刻加载相关联对象集合,与延迟加载相反。我们可以使用三种方法来立即加载,,分别是:可选的lazy属性、NHibernate提供的实用类、HQL抓取策略。下面依次用实例分析其中的机制。

实例分析1.一对多关系实例

在一对多关系实例中,我们使用Customer对象与Order对象为例,在数据访问层中依然使用上一篇的方法,这里使用强制关闭Session的方法,为什么使用Using强制释放资源呢?我就是想利用这个来模拟Web应用程序中的Session机制。用这个分析比没有Using释放资源更有意义。

数据访问层中方法:加载Customer对象并使用Using强制清理关闭Session

public Customer LazyLoadUsingSession(int customerId){using (ISession _session = new SessionManager().GetSession()){return _session.Get<Customer>(customerId);}}1.使用lazy="false"属性

在上一篇我们一直没有修改映射文件即一直默认是lazy="true",NHibernate就采用了默认的延迟加载。

这里介绍第一种方法就是修改映射文件来立即加载,打开Customer.hbm.xml文件,在Set元素中添加lazy="false"。

编写一个测试验证,调用数据访问层中的使用Using强制资源清理Session加载Customer对象的方法加载一个Customer对象,NHibernate这时立即加载Customer相关联的Order对象。利用NHibernate提供实用类(NHibernateUtil)测试被关联的Customer对象集合是否已初始化(也就是已加载)。

[Test]public void EagerLoadUsingLazyFalseTest(){Customer customer = _relation.LazyLoadUsingSession(1);Assert.IsTrue(NHibernateUtil.IsInitialized(customer.Orders));}

测试成功,证明NHibernate立即加载了Order对象,发现生成两句SQL语句:第一条查询Customer对象,第二条语句查询其相关联的Order对象集合。

,,,Lastname9_0_’1′,,,,,Customer6_0_

不过,细心的朋友会发现,这时Orders对象集合的类型是Iesi.Collections.Generic.HashedSet`1[DomainModel.Entities.Order],上一节只有在没有使用Using强制关闭资源下,Orders对象集合才是这个类型,在使用强制关闭资源的情况下,Orders对象集合的类型为:NHibernate.Collection.Generic.PersistentGenericSet<DomainModel.Entities.Order> ,进一步读取Order项抛出HibernateException异常。我想从这个角度也说明了立即加载机制。

好了,这就说到这里,还是把映射文件改为原来默认的吧(即去掉lazy="false"),看看还有其它什么方法来立即加载。

2.使用NHibernateUtil实用类

NHibernate提供实用类(NHibernateUtil)不光光只是用来测试被关联的对象集合是否已初始化,还有一个非常重要的功能就是可以强制初始化未初始化的相关联的对象。有了这个功能,我们就可以修改数据访问层中的方法,把上面使用Using强制清理关闭Session的方法中加上NHibernateUtil类提供Initialize方法来初始化Customer相关联的Order对象集合。

public Customer EagerLoadUsingSessionAndNHibernateUtil(int customerId){using (ISession _session = new SessionManager().GetSession()){Customer customer= _session.Get<Customer>(customerId);NHibernateUtil.Initialize(customer.Orders);return customer;}}

我们编写一个方法来测试一下:

[Test]public void EagerLoadUsingSessionAndNHibernateUtilTest(){Customer customer = _relation.EagerLoadUsingSessionAndNHibernateUtil(1);Assert.IsTrue(NHibernateUtil.IsInitialized(customer.Orders));}

测试成功,这个结果同修改映射文件一样。

2.多对多关系实例1.使用lazy="false"属性

同理,使用lazy="false"属性来设置立即加载行为,这时在持久化类中就不必为其公共方法、属性和事件声明为virtual属性了,因为没有使用延迟加载。不过在这里我还是推荐大家使用NHibernate默认的延迟加载行为,原因很简单,NHibernate延迟加载性能上可以提高很多,在特殊情况下使用下面的方法来立即加载。

这个例子同上面类似,这里就不举重复的例子了,大家自己测试下就可以了。

2.使用NHibernateUtil实用类

如果你需要获得Order实体的相关联对象可以使用NHibernateUtil类初始化关联对象(把他们从数据库取出来)。看看下面数据访问层中的方法,使用NHibernateUtil类提供Initialize方法初始化相关联的Customer和Product对象。

public DomainModel.Entities.OrderEagerLoadOrderAggregateSessionAndNHibernateUtil(int orderId){using (ISession _session = new SessionManager().GetSession()){DomainModel.Entities.Order order =_session.Get<DomainModel.Entities.Order>(orderId);NHibernateUtil.Initialize(order.Customer);NHibernateUtil.Initialize(order.Products);return order;}}要愈合不能,要忘却不能,要再次拥抱,却鼓不起足够的勇气,

NHibernate之旅(13):初探立即加载机制

相关文章:

你感兴趣的文章:

标签云: