准备工作
Customer
public class Customer
{
public virtual int Unid { get; set; }
public virtual DateTime CreateTime { get; set; }
public virtual string Address { get; set; }
public virtual int Version { get; set; }
private IList<Order> _orderList = new List<Order>();
public virtual IList<Order> Orders
{ get { return _orderList; } set { _orderList = value; } }
}
Order
public class Order
{
public virtual int Unid { get; set; }
public virtual int Version { get; set; }
public virtual DateTime? CreateTime { get; set; }
public virtual Customer Customer { get; set; }
public virtual string Memo { get; set; }
}
Customer mapping
<class name="Customer" table="Customer" lazy="true">
<id name="Unid" column="Unid">
<generator class="identity"></generator>
</id>
<version name="Version" column="Version" type="integer" unsaved-value="0"></version>
<property name="CreateTime" column="CreateTime" insert="false" update="false"></property>
<property name="Address" column="Address"></property>
<bag name="Orders" table="POrder" cascade="all" inverse="true" lazy="false">
<key column="CustomerId"></key>
<one-to-many class="Domain.Entities.Order,Domain"/>
</bag>
</class>
Order mapping
<class name="Order" table="POrder">
<id name="Unid" column="Unid">
<generator class="identity"></generator>
</id>
<version name="Version" column="Version" type="integer" unsaved-value="0"></version>
<property name="CreateTime" column="CreateTime"></property>
<property name="Memo" column="Memo"></property>
<many-to-one name="Customer" column="CustomerId"
class="Domain.Entities.Customer,Domain" not-null="true"></many-to-one>
</class>
场景描述:这是在一对多的关系下。
(一)使用延迟加载
默认情况下是延迟加载,可以显示声明为延迟加载:
<class name="Customer" table="Customer" lazy="true">
这时,做为集合的属性Orders映射应该默认也是延迟(待证),所以bag的lazy属性也是true
(1)在会话未结束时加载分析
方法LoadLazy(),用于在会话间延迟加载
ISession _Session = NHBSessionFactory.GetSession;
public Customer LoadLazy(int iUnid)
{
_Session = NHBSessionFactory.GetSession;
return _Session.Get<Customer>(iUnid);
}
测试一:
Customer cc = hh.LoadLazy(38); |
只执行这步。
结论:
·执行一句查询
·此时,Orders属性已经被填充,集类型为:
Orders {Domain.Entities.Order}
System.Collections.Generic.IList<Domain.Entities.Order>
{NHibernate.Collection.Generic.PersistentGenericBag
<Domain.Entities.Order>}
测试二:
接上句,执行:
IList<Order> _list = cc.Orders; |
结论:
·执行两条查询
·Orders属性已经被填充,集类型同上
在未结束的本次会话中,延迟加载会正常进行;而且当延迟加载时,如果不需要被延迟的部分(Orders属性),那么效率会高些。
(2)会话结束后的延迟加载
public Customer LoadUseSession(int iUnid)
{
using (_Session)
{
Customer cc=_Session.Get<Customer>(iUnid);
return cc;
}
}
测试一:
Customer cc = hh.LoadUseSession(38); |
只执行到这步。
结论:
·执行一条查询
·此时,Orders属性已经被填充,集类型为:
Orders {Domain.Entities.Order}
System.Collections.Generic.IList<Domain.Entities.Order>
{NHibernate.Collection.Generic.PersistentGenericBag
<Domain.Entities.Order>}
·Orders属性填充有异常:NHibernate.LazyInitializationException
测试二:
接上句执行:
IList<Order> _list = cc.Orders; |
·也执行了一条查询
·有异常发生,不能加载数据
在延迟机制下,会话间断时,不能正常加载一对多关系中的多的数据,也就是一对多关系中一的一方的多方集合的属性不能被正常填充。
总结:在应用延迟策略的情况下,在一对多关系的情况下,如果会话间断,会不能正常访问被延迟加载的数据。但在会话期间,应用延迟策略会提高效率。
(二)使用立即加载
默认情况下应用延迟加载,通过修改:
<class name="Customer" table="Customer" lazy="false">
来启动立即加载。此时,Customer应用了立即加载,如果它的集合属性(Orders),不设置lazy属性,则集合属性还用默认值,即仍使用延迟加载。所以还要显示的声明Orders集合的lazy属性为不延迟:
<bag name="Orders" table="POrder" cascade="all" inverse="true" lazy="false">
<key column="CustomerId"></key>
<one-to-many class="Domain.Entities.Order,Domain"/>
</bag>
(1)在会话未结束时加载分析
测试一:
只执行:
Customer cc = hh.LoadLazy(38); |
结论:
·执行两条查询
·Orders属性被填充
测试二:
接着执行:
IList<Order> _list = cc.Orders; |
结论:
·执行两条查询
·Orders属性访问正常
在立即加载机制下,不管是什么情况,只要是申请了一对多关系下一的一方的实例,就会执行两条查询,此时的Oders属性确实已经被填充了。
(2)会话间断后加载分析
测试一:
只执行:
Customer cc = hh.LoadUseSession(38); |
结论:
·执行两条查询
·Orders被填充,但不会发生异常
测试二:
接着执行:
IList<Order> _list = cc.Orders; |
结论:
·执行两条查询
·Orders被填充
·Orders访问正常
结论:
·设置立即加载,需要对Bag属性声明lazy=false属性
·在立即加载策略下,一对多关系下的数据申请,与会话间断无关,因为数据在会话未间断之前已经被立即加载了。