目录

写在前面

文档与系列文章

立即加载

一个例子

总结

写在前面

上篇文章介绍了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、一对多关系

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

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

1.1、修改Customer.hbm.xml文件

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

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

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

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

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

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

查看生成的sql语句

 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'

 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,或者删除该属性。

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

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

2、多对多关系

2.1、使用Lazy=“false”属性

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

2.2、使用NHibernateUtil实用类

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

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

        /// <summary>
/// NHibernateUtil方式,立即加载订单与商品
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public Order GetOrderProductByImmediatelyLoadNHibernateUtil(Guid orderId)
{
using (var session = NHibernateHelper.GetSession())
{
var order = session.Get<Wolfy.Shop.Domain.Entities.Order>(orderId);
//强制初始化customer
NHibernate.NHibernateUtil.Initialize(order.Customer);
//强制初始化Product
NHibernate.NHibernateUtil.Initialize(order.Products);
return order;
}
}

测试

查看生成的sql语句

 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'

 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'

 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。

2.3使用HQL抓取策略

HQL语句支持的连接类型为:inner join(内连接)、left outer join(左外连接)、right outer join(右外连接)、full join(全连接,不常用)。

“抓取fetch”连接允许仅仅使用一个选择语句就将相关联的对象随着他们的父对象的初始化而被初始化,可以有效的代替了映射文件中的外联接与延迟属性声明。

几点注意:

  • fetch不与setMaxResults() 或setFirstResult()共用,因为这些操作是基于结果集的,而在预先抓取集合时可能包含重复的数据,也就是说无法预先知道精确的行数。
  • fetch还不能与独立的with条件一起使用。通过在一次查询中fetch多个集合,可以制造出笛卡尔积,因此请多加注意。对多对多映射来说,同时join fetch多个集合角色可能在某些情况下给出并非预期的结果,也请小心。
  • 使用full join fetch 与 right join fetch是没有意义的。 如果你使用属性级别的延迟获取,在第一个查询中可以使用 fetch all properties 来强制NHibernate立即取得那些原本需要延迟加载的属性。

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

测试代码

        /// <summary>
/// HQL方式,立即加载订单与商品
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public Order GetOrderProductByImmediatelyLoadHQL(Guid orderId)
{
using (var session = NHibernateHelper.GetSession())
{
return session.CreateQuery("from Order o" +
" left outer join fetch o.Products" +
" inner join fetch o.Customer where o.OrderID=:orderId")
.SetGuid("orderId", orderId)
.UniqueResult<Order>();
}
}

生成的sql语句

总结

这篇文章介绍了nhibernate立即加载的方式,什么时候使用立即加载,什么时候使用延迟加载,视项目中的情况而定。

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

[NHibernate]立即加载的更多相关文章

  1. NHibernate动态加载资源文件

    最近做项目,又用到了以前做过的ORM框架--NHibernate. 此次想要实现的目标: 1.简单SQL用NHibernate的Session的CRUD方法实现 2.复杂SQL用Native SQL实 ...

  2. 一步步学习NHibernate(5)——多对一,一对多,懒加载(2)

    请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们建立了Student和Clazz之间的关联属性,并从Student(many)的一方查看了Clazz的信 ...

  3. [转]NHibernate之旅(13):初探立即加载机制

    本节内容 引入 立即加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过上一篇的介绍,我们知道了NHibernate中默认的加载机制——延迟加载.其本质就是使用GoF23中代理模式 ...

  4. NHibernate教程(13)--立即加载

    本节内容 引入 立即加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过上一篇的介绍,我们知道了NHibernate中默认的加载机制--延迟加载.其本质就是使用GoF23中代理模式 ...

  5. 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询

    相关资料: http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html 问题的提出: 1.延迟加载,可能会引起session已经关闭的异常,例 ...

  6. 一步步学习NHibernate(4)——多对一,一对多,懒加载(1)

    请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们学会如何使用NHibernate对数据的简单查询,删除,更新和插入,那么如果说仅仅是这样的话,那么NHi ...

  7. NHibernate 延迟加载与立即加载 (第七篇)

    NHibernate 延迟加载与立即加载 (第七篇) 一.延迟加载 延迟加载可以理解为:当需要用的时候才加载. 假设我们数据库有一个Person对象,一个Country对象,其中Person属于Cou ...

  8. Hibernate 延迟加载和立即加载

    概念 什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取. 什么是立即加载:所谓立即加载既是 ...

  9. 浅谈Entity Framework中的数据加载方式

    如果你还没有接触过或者根本不了解什么是Entity Framework,那么请看这里http://www.entityframeworktutorial.net/EntityFramework-Arc ...

随机推荐

  1. 3-1 Linux文件管理类命令详解

    根据马哥Linux初级 03-01整理 1. 目录管理 ls cd pwd mkdir rmdir tree 2. 文件管理 touch stat file rm cp mv nano 3. 日期时间 ...

  2. XML 序列化与反序列化

    XML序列化与反序列化 1.将一个类转化为XML文件 /// <summary> /// 对象序列化成XML文件 /// </summary> /// <param na ...

  3. CentOS 6.5下Redis安装记录

    Redis简介: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工 ...

  4. BroadcastReceiver详解

    详解 2014-08-20 19:42 13492人阅读 评论(8) 收藏 举报 分类: 5.andriod开发(148) 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+] ...

  5. [MVC]如何删除文章内容中的图片

    1.实现代码 if (!string.IsNullOrWhiteSpace(entity.Content)) { var immgList = TextHelper.GetImgUrlList(ent ...

  6. CSS实现背景透明,文字不透明(兼容各浏览器)

    在 FF/Chrome 等较新的浏览器中可以使用css属性background- color的rgba轻松实现背景透明,而文字保持不透明.而IE6/7/8浏览器不支持rgba,只有使用IE的专属滤镜f ...

  7. 简单CSS3实现炫酷读者墙

    如题,给大家介绍和讲解几个常用的CSS3属性,并用到实处. 先看demo(请使用Chrome或者Firefox浏览,IE的靠边): 点此查看实例 觉得爽的可以继续阅读下面的知识点,感觉不爽的可绕行. ...

  8. 跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  9. Mysql查看执行计划-explain

    最近生产环境有一些查询较慢,需要优化,于是先进行业务确认查询条件是否可以优化,不行再进行sql优化,于是学习了下Mysql查看执行计划. 语法 explain <sql语句>  例如: e ...

  10. C#-WebForm-表单元素

    表单元素共12个,分三大类: 文本类: <input type="text" /> - 文本框 <input type="password" ...