解决实体载入的性能问题 - Lazy Load,延迟载入

[本文转载自 http://www.agilelabs.cn/blogs/woody/archive/2005/09/22/48.aspx]

因为AR把数据库中的外键关系全部采用对象间的聚合关系表现了出来,例如:

实体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载入内存
string blogName = blog.BlogName; //到下面这一步,AR框架才会为我们从库中把相应的Post载入,从而达到延迟载入
int postCount = blog.Posts.Count; }
    请注意 new SessionScope() 。因为在执行int postCount = blog.Posts.Count 的时候才会执行从数据库中载入相应数据的步骤。所以,在此时必须存在一个NHibernate的ISession,不然Castle框架将无法从库载入数据,从而引发一个"NHibernate.LazyInitializationException : Failed to lazily initialize a collection - no session"异常。因此,再得到blog实体后,为了进行延迟载入,我们必须把这个Session保持下来,于是有了这个SessionScope。

你可能感兴趣的:(load)