• 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属性

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

  • 相关阅读:
    bootmgr is missing
    【转】ahci和IDE的区别
    win10系统故障代码:0xc000014c
    c++小数点后舍入
    关于类里再声明自身类实例的思考
    Java集合
    Python图片转字符画
    102. Binary Tree Level Order Traversal
    1041. Robot Bounded In Circle
    144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/jams742003/p/1641262.html
Copyright © 2020-2023  润新知