NHibernate初探(七) 一对多关系延迟机制

准备工作

 

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映射应该默认也是延迟(待证),所以baglazy属性也是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属性

·在立即加载策略下,一对多关系下的数据申请,与会话间断无关,因为数据在会话未间断之前已经被立即加载了。

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

上一篇:Ioc的推荐实现方式


下一篇:NHibernate VS .NET Type VS DbType 的类型映射关系