这篇文章

http://ayende.com/blog/3988/nhibernate-the-difference-between-get-load-and-querying-by-id

One of the more common mistakes that I see people doing with NHibernate is related to how they are loading entities by the primary key. This is because there are important differences between the three options.

The most common mistake that I see is using a query to load by id. in particular when using Linq for NHibernate.

var customer = (
select customer from s.Linq<Customer>()
where customer.Id = customerId
select customer
).FirstOrDefault();
Every time that I see something like that, I wince a little inside. The reason for that is quite simple. This is doing a query by primary key. The key word here is a query. This means that we have to hit the database in order to get a result for this query. Unless you are using the query cache (which by default you won’t), this force a query on the database, bypassing both the first level identity map and the second level cache. Get and Load are here for a reason, they provide a way to get an entity by primary key. That is important for several aspects, most importantly, it means that NHibernate can apply quite a few optimizations for this process.

好像在说,不要用主键(by primary key)去查询,因为用主键区查询会绕开一级和二级缓存。

所以建议用Get和Load去查询

下面的测试是错误的,要看正确的盖棺定论,请跳转至:
终极测试:

--------------------------------------------

实现延迟加载:

如何实现延迟加载:

要在实现延迟加载的类的映射文件xxx.hbm.xml中添加  lazy="true",根据加的位置,有两种:

一是类级别的:

  <class name="Model.Customer, Model"
table="Customer"
discriminator-value="0" lazy="true">
<!--unsaved-value="0" 主键表中不需要定义,而是需要在子表中定义-->
<id name="CustomerId"
column="CustomerId"
type="int"
unsaved-value="0">
<generator class="native" />
。。。。

二是集合级别的

  <class name="Model.Customer, Model"
table="Customer"
discriminator-value="0">
。。。。。
<set name="Orders" table="Order" lazy="true"
generic="true"
inverse="true" cascade="all">
<key column="CustomerId" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Model.Order,Model"/>
</set>
。。。

根据目前的测试,集合位置的延迟加载配置会覆盖类级别的延迟加载配置。

有两种获取实体的方法:Get和Load方法。测试了如下组合:

类级别的lazy="true"  且                 类级别的lazy="true"且

集合级别的lazy="true"                  集合级别的lazy="false"

--------------------------------------------------------------------------

Get方法     |        加载父,延迟加载子                     父子都非延迟加载

Load方法   |        父子都非延迟加载                        父子都非延迟加载

从上面可以看到:

Load方法是不理会lazy="true" 配置的,永远的是非延迟加载。用Lode方法获取Customer时,Customer和子集合Order永远都是立即加载(不管哪里配置了lazy =“true”)。

刚好和:

http://blog.knowsky.com/192505.htm

描述的完全相反。到底谁对谁错,纠结啊

通过一夜的调试:

发现,如果是设断点去调试,那么Load表现为非延迟加载,发送了SQL语句,

这可能是编译器的问题。上面说的

刚好和:

http://blog.knowsky.com/192505.htm

描述的完全相反。到底谁对谁错,纠结啊


应该可以更正回来了,

类级别的lazy="true"  且                 类级别的lazy="true"且

集合级别的lazy="true"                  集合级别的lazy="false"

--------------------------------------------------------------------------

Get方法     |        加载父,延迟加载子                     父子都非延迟加载

Load方法   |        父子都延迟加载                          父子都非延迟加载

最终的结论是:

在配置lazy = “true”的情况下,

Get方法仅延迟加载子集合Orders,

Load方法比Get更牛逼,不仅延迟加载子集合Orders,把父Customer也延迟加载了。

Load方法是假设父Customer是存在,若不存在,会引发异常“NHibernate.ObjectNotFoundException”类型的异常,

但是这种异常,Nhibernate自己内部处理了,并返回一个实体类的代理(CustmoeProxy),保证不返回一个null

如下图所示:

------------------------------------------

非延迟加载图解:

延迟加载图解:

看到,当实现延迟加载,当需要Orders时,会通过session去查询,session。但此时,由于session已经关闭,

所以会抛出异常:

{"Initializing[Model.Customer#336]-failed to lazily initialize a collection of role: Model.Customer.Orders, no session or session was closed"}
为了避免session被关闭,延迟加载失败。有如下解决方案:
public Orders LazyLoadOrders(int customerId)
{
using (ISession _session = new SessionManager().GetSession())
{
return _session.Get<Customer>(customerId).Orders;
}
}

以后就调用这个方法来获取Orders

--------------------------------------------------------------------------------------------------------------
终极测试: 注意:测试时不要打断点,否则会影响测试结果(如果打了断点调试,会有多余的SQl请求产生),上面的测试就是因为打了断点去测试,结果
影响了测试结论。 测试的最终结论,上面所以的测试结论以下面的测试结果为盖棺定论。 下面的<class>和<Set>都是属于Customer.hbm.xml中的设置。

【1】Get方法:

<class  name ="Customer" lazy="true" >     <class  name ="Customer" lazy="false" >

<set name="Orders" lazy="true">        加载Customer,不加载Orders                         加载Customer,不加载Orders

<set name="Orders" lazy="false">       加载Customer,   加载Orders                         加载Customer,    加载Orders

    结论:1.Get方法永远加载Customer;
2.Get方法是否加载Orders,由<set name="Orders" lazy="">决定。  【2】Load方法:

<class  name ="Customer" lazy="true" >     <class  name ="Customer" lazy="false" >

<set name="Orders" lazy="true">        Customer和Orders都不加载                          加载Customer,不加载Orders

<set name="Orders" lazy="false">       Customer和Orders都不加载                          加载Customer,加载Orders

    结论:1.Load方法只要Class的Lazy为false,永远都不加载Customer和Orders;
2.Load方法只要Class的Lazy为ture,永远加载Customer,是否加载Oders由<set name="Orders" lazy="">决定。 

01-05-01-1【Nhibernate (版本3.3.1.4000) 出入江湖】延迟加载及其class和集合(set、bag等)的Lazy属性配置组合对Get和Load方法的影响的更多相关文章

  1. 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存

    一.准备工作 [1]根据操作系统(位数)选择下载相应版本的MemCache, MemCache的下载和安装,参看: http://www.cnblogs.com/easy5weikai/p/37606 ...

  2. 01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题

    此文由于当时不知道NHibernate的Sava方法不是更新操作,不知道Save就是Add,造成如下荒唐的求证过程,但结论是对的 ,可报废此文,特此声明. NHibernate--Save方法: Cu ...

  3. 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存

    缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...

  4. 01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询

    Criteria API关联查询 如果说HQL查询还有需要了解点SQL语法知识,并不是完全彻底面向对象查询, 那么Criterial API就是完全面向对象的查询方式. public IList< ...

  5. 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制

    Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: ...

  6. 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理

    http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 管理NHibernate二级缓存 NHibernate二级缓存由ISessionF ...

  7. 01-08-04【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之命名缓存

    http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 可以在映射文件中定义命名查询,<query>元素提供了很多属性,可以用 ...

  8. 01-08-02【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider

    第一步骤:hibernate.cfg.xml文件补上如下配置: <?xml version="1.0" encoding="utf-8"?> < ...

  9. 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态

    以下属于不明来源资料: 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根 ...

随机推荐

  1. 利用 NUget包 EPPlus 实现数据导出到Excel(适用于MVC)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvoAAABpCAIAAADEEBBGAAAJdElEQVR4nO3cy2ob5wLA8TxKnqTrrr

  2. 20141017--类型String类

    Console.Write("请输入您的身份证号"); string x=Console.ReadLine();//小string是大String的快捷方式 int i = x.L ...

  3. mysql 存储过程详解 存储过程

    mysql存储过程详解 1.      存储过程简介         我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成 ...

  4. 了解GDAL的图像处理/Python

    GDAL是一个操作各种栅格地理数据格式的库.包括读取.写入.转换.处理各种栅格数据格式(有些特定的格式对一些操作如写入等不支持).它使用了一个单一的抽象数据模型就支持了大多数的栅格数据(GIS对栅格, ...

  5. OpenGL第12-14讲小结

    首先要为自己为什么没有写第10讲的控制3D场景和第11讲的红旗飘飘呢?因为没看啊~哈哈哈,而且我尝试着运行红旗飘飘的时候电脑蓝屏了(可能不是它的锅),暂时跳过了. 恩,12到14主要了解了这么些东西, ...

  6. 工厂方法(Factory Method)模式

    一.工厂方法(Factory Method)模式 工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟的子类中. 工厂方法模式是简单工厂 ...

  7. Windows phone 中一些实用的控件

    一.TextBlock:这个控件其实就是Label控件. <TextBlock x:Name="PageTitle" Text="page name" M ...

  8. NDK jni 加载静态库

    加载静态库到android,静态库的提供方式有2种, a. 通过源文件来编译静态库 b. 加载已经编译好的静态库 首先我们来看,通过源文件来编译静态库,工程目录如下 第一步:我们来看我们的jni目录, ...

  9. C++ 中的 const 详解

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4235721.html 1.为什么使用 const int 而不使用 #define 在使用# ...

  10. Berkeley DB数据处理

    设计一个结构,利用Berkeley DB完成大数据的存储,备份,查询功能. 已有的储备: 1.Berkeley DB的基本操作. 2.数据转存后数据不丢失. 3.过百GB以上数据的存储. 数据流如下, ...