zoukankan      html  css  js  c++  java
  • NHibernate

    NHibernate]立即加载

    目录

    写在前面

    文档与系列文章

    立即加载

    一个例子

    总结

    写在前面

    上篇文章介绍了nhibernate延迟加载的相关内容,简单回顾一下延迟加载,就是需要的时候再去加载,需要的时候再向数据库发出sql指令进行查询。

    本篇文章介绍的立即加载,则和延迟加载相对,举个简单的例子,就是查询客户信息,则会将该客户相关联的数据立即进行加载。实现立即加载的方式有三种:设置映射文件中节点的可选属性lazy,Nhibernate提供的实用类,HQL抓取策略。

    文档与系列文章

    [Nhibernate]体系结构

    [NHibernate]ISessionFactory配置

    [NHibernate]持久化类(Persistent Classes)

    [NHibernate]O/R Mapping基础

    [NHibernate]集合类(Collections)映射 

    [NHibernate]关联映射

    [NHibernate]Parent/Child

    [NHibernate]缓存(NHibernate.Caches)

    [NHibernate]NHibernate.Tool.hbm2net

    [NHibernate]Nullables

    [NHibernate]Nhibernate如何映射sqlserver中image字段

    [NHibernate]基本配置与测试 

    [NHibernate]HQL查询 

    [NHibernate]条件查询Criteria Query

    [NHibernate]增删改操作

    [NHibernate]事务

    [NHibernate]并发控制

    [NHibernate]组件之依赖对象

    [NHibernate]一对多关系(级联删除,级联添加)

    [NHibernate]一对多关系(关联查询)

    [NHibernate]多对多关系(关联查询)

    [NHibernate]延迟加载

    立即加载

    一个例子

    1、一对多关系

    通过立即加载的方式,加载客户信息及客户的订单信息。

    复制代码
     1         /// <summary>
     2         /// 采用立即加载的方式加载客户信息
     3         /// </summary>
     4         /// <param name="customerID"></param>
     5         /// <returns></returns>
     6         public Customer GetCustomerByImmediatelyLoad(Guid customerID)
     7         {
     8             //获得ISession实例
     9             //通过using的方式将session释放,为了保证是立即加载的数据,而不是延迟加载的
    10             //还记得上篇文章中提到的在延迟加载中,在关闭session情况下,再读取数据的时候就会有一个异常信息
    11             //忘记的可以再回到上一篇文章进行查看
    12             using (ISession session = NHibernateHelper.GetSession())
    13             {
    14                 return session.Get<Customer>(customerID);
    15             }
    16         }
    复制代码

    1.1、修改Customer.hbm.xml文件

    因为nhibernate默认是使用Lazy的方式加载数据的,也就是默认Lazy=“true”的,需要显示的指定Lazy=“false”。

    1     <!--一对多关系:一个客户可以有一个或者多个订单-->
    2     <!--子实体负责维护关联关系-->
    3     <set name="Orders" table="TB_Order" generic="true" inverse="true" cascade="all" lazy="false">
    4       <key column="CustomerID" foreign-key="FK_TB_Order_TB_Customer"></key>
    5       <one-to-many class="Wolfy.Shop.Domain.Entities.Order,Wolfy.Shop.Domain"/>
    6     </set>

    编写一个测试验证,调用数据访问层中的使用using强制资源清理Session加载Customer对象的方法加载一个Customer对象,NHibernate这时立即加载Customer相关联的Order对象。

    利用NHibernate提供实用类(NHibernateUtil)测试被关联的Customer对象集合是否已初始化(也就是已加载)。

    上篇文章中也说明了,如果在关闭session的情况下,如果你展开customer的orders属性,就会出现异常

    这也说明了Orders是跟customer一样立即加载的。

    查看生成的sql语句

    1 exec sp_executesql N'SELECT customer0_.CustomerID as CustomerID0_0_, customer0_.Version as Version0_0_, customer0_.CustomerName as Customer3_0_0_, customer0_.CustomerAddress as Customer4_0_0_ FROM TB_Customer customer0_ WHERE customer0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'
    2 
    3 exec sp_executesql N'SELECT orders0_.CustomerID as CustomerID1_, orders0_.OrderID as OrderID1_, orders0_.OrderID as OrderID1_0_, orders0_.OrderDate as OrderDate1_0_, orders0_.CustomerID as CustomerID1_0_ FROM TB_Order orders0_ WHERE orders0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'

    第一条sql为查询Customer的,第二条sql是查询与该customer相关联的order的。

    1.2、使用NHibernateUtil实用类

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

    修改Customer.hbm.xml文件,将set节点的lazy属性设置为默认值true,或者删除该属性。

    复制代码
     1         /// <summary>
     2         /// NHibernateUtil方式,立即加载客户信息及关联的数据
     3         /// </summary>
     4         /// <param name="customerID"></param>
     5         /// <returns></returns>
     6         public Customer GetCustomerByImmediatelyLoadNHibernateUtil(Guid customerID)
     7         {
     8             //获得ISession实例
     9             //通过using的方式将session释放,为了保证是立即加载的数据,而不是延迟加载的
    10             //还记得上篇文章中提到的在延迟加载中,在关闭session情况下,再读取数据的时候就会有一个异常信息
    11             //忘记的可以再回到上一篇文章进行查看
    12             using (ISession session = NHibernateHelper.GetSession())
    13             {
    14                 Customer customer = session.Get<Customer>(customerID);
    15                 //
    16                 // 摘要: 
    17                 //     Force initialization of a proxy or persistent collection.
    18                 //
    19                 NHibernate.NHibernateUtil.Initialize(customer.Orders);
    20                 return customer;
    21             }
    22         }
    复制代码

    通过该种方式,跟上面的测试结果相同,就不再贴图了。

    2、多对多关系

    2.1、使用Lazy=“false”属性

    例子同上面的类似,就不再赘述。

    2.2、使用NHibernateUtil实用类

    这里采用Order和Product多对多实例进行分析。

    如果想在加载Order的情况下,加载该Order下的所有Product,可以使用NHibernateUtil类初始化关联对象(把他们从数据库取出来)。

    复制代码
     1        /// <summary>
     2         /// NHibernateUtil方式,立即加载订单与商品
     3         /// </summary>
     4         /// <param name="customerID"></param>
     5         /// <returns></returns>
     6         public Order GetOrderProductByImmediatelyLoadNHibernateUtil(Guid orderId)
     7         {
     8             using (var session = NHibernateHelper.GetSession())
     9             {
    10                 var order = session.Get<Wolfy.Shop.Domain.Entities.Order>(orderId);
    11                 //强制初始化customer
    12                 NHibernate.NHibernateUtil.Initialize(order.Customer);
    13                 //强制初始化Product
    14                 NHibernate.NHibernateUtil.Initialize(order.Products);
    15                 return order;
    16             }
    17         }
    复制代码

    测试

    查看生成的sql语句

    复制代码
    1 exec sp_executesql N'SELECT order0_.OrderID as OrderID1_0_, order0_.OrderDate as OrderDate1_0_, order0_.CustomerID as CustomerID1_0_ FROM TB_Order order0_ WHERE order0_.OrderID=@p0',N'@p0 uniqueidentifier',@p0='78A53F67-A293-48A1-BBE2-86FED77342FA'
    2 
    3 exec sp_executesql N'SELECT customer0_.CustomerID as CustomerID0_0_, customer0_.Version as Version0_0_, customer0_.CustomerName as Customer3_0_0_, customer0_.CustomerAddress as Customer4_0_0_ FROM TB_Customer customer0_ WHERE customer0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'
    4 
    5 exec sp_executesql N'SELECT products0_.OrderID as OrderID1_, products0_.ProductID as ProductID1_, product1_.ProductID as ProductID3_0_, product1_.Name as Name3_0_, product1_.Price as Price3_0_ FROM TB_OrderProduct products0_ left outer join TB_Product product1_ on products0_.ProductID=product1_.ProductID WHERE products0_.OrderID=@p0',N'@p0 uniqueidentifier',@p0='78A53F67-A293-48A1-BBE2-86FED77342FA'
    复制代码

    这里生成了三条sql语句,查询和Order关联的customer和Product。

    上篇文章中,描述了一个N+1的问题,这里再次说明一下,N+1的问题,我是这样理解的你本来想要一条,可是采用默认延迟加载的情况下,就会把所有的信息都加载,有点浪费,而这时采用立即加载的方式,你可以很好的控制,想加载几条加载几条。

    总结

    这篇文章介绍了nhibernate立即加载的方式,什么时候使用立即加载,什么时候使用延迟加载,视项目中的情况而定。比如这种情况,如果在多对多的关系中,你想加载几条数据,也就是N+1的问题,还是采用立即加载的方式更好,此时,不会加载多余的数据,可以更好的达到控制的目的。

    参考文章:http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html

     

     
     
  • 相关阅读:
    Replication:The replication agent has not logged a progress message in 10 minutes.
    分区管理
    获取URL最后一个 ‘/’ 之后的字符
    Replication 第四篇:事务复制中Subscriber的主键列是只读的
    窗口和窗口函数
    SQL Server 日期格式和日期操作
    约束4:唯一约束,Check约束和null
    约束3:default约束
    Merge语句中NULL的陷阱
    查询“全部”
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4082455.html
Copyright © 2011-2022 走看看