实体Blog对象中会包含一个IList Posts的属性,以表示他们之间的关系。这样,只要通过 Blog blog = Blog.fine(id); 得到一个Blog实体,内存中就会同样生成与其相关的Post对象。
但是,在一个大的系统中,这种对象间的关系会非常复杂 (Blog对象可能还会和Community之间存在关系,还可能和PostCategory存在关系......)。于是,得到一个Blog对象的同时,可能得到其他与之相关的N多个对象 (想想你的数据库设计,不要小看这个N)。但是这些象都可能是暂时不需要的,但仍然被载入内存,这将严重影响系统的性能。
对与这个问题,可以使用"Lazy Load"---延迟载入。为对象间关系的属性打上 Lazy的标签。这样,当你new Blog的时候,不会把于其相关的Post,Community......载入内存。只有当你真正需要那些对象时,比如,进行 Blog.Posts 调用时,框架会 自动为我们从数据库中得到我们所需要的东西。
例子如下:
在Blog实体中,存在一个Posts的属性,表明该Blog发表的所有Post,先看看在Blog里是怎样声明这个东西的:
[HasMany(
typeof
(Post), Table
=
"
Post
"
, ColumnKey
=
"
BlogId
"
)]
public
System.Collections.IList Posts {
get
{
return
this
.posts; }
set
{
this
.posts
=
value; } }
这样的话,每生成一个Blog对象,就会把和他相关的Post对象全部载入,现在我们来为他打上Lazy Load的标签,很简单,只需要在特性中指明“Lazy=true”
[HasMany(
typeof
(Post), Table
=
"
Post
"
, ColumnKey
=
"
BlogId
"
,Lazy
=
true
)]
OK。现在这个Posts属性已经具备了延迟载入的能力。我们来看一下他的运行过程怎么样的。
using(new SessionScope()) { Blog blog = Blog.Find(96); //通过Blog类的静态方法得到一个Blog实体 //此时,blog对象里面的Posts属性并没有把相应的Post载入内存请注意 new SessionScope() 。因为在执行int postCount = blog.Posts.Count 的时候才会执行从数据库中载入相应数据的步骤。所以,在此时必须存在一个NHibernate的ISession,不然Castle框架将无法从库载入数据,从而引发一个"NHibernate.LazyInitializationException : Failed to lazily initialize a collection - no session"异常。因此,再得到blog实体后,为了进行延迟载入,我们必须把这个Session保持下来,于是有了这个SessionScope
string blogName = blog.BlogName; //到下面这一步,AR框架才会为我们从库中把相应的Post载入,从而达到延迟载入
int postCount = blog.Posts.Count; }