使用ActiveRecord在nHibernate中快速加载惰性加载的实体

使用ActiveRecord在nHibernate中快速加载惰性加载的实体,nhibernate,activerecord,lazy-loading,castle-activerecord,aggregateroot,Nhibernate,Activerecord,Lazy Loading,Castle Activerecord,Aggregateroot,我正在从事一个项目,该项目有一个丰富的对象模型,其中包含多组聚合根 我们正在使用Castle堆栈(通过ActiveRecord单轨传输到nHibernate) 我们已经将聚合根标记为lazy[ActiveRecord(lazy=true)],并在我们的存储库中定制了“渴望”例程以渴望获取对象图。我们使用HQL从根目录的子集合中定义急切获取 e、 g.如果Account是聚合根目录(并标记为lazy-loaded),我们将立即获取Account。。命令。。完整图形的产品实体 到目前为止(希望如此)

我正在从事一个项目,该项目有一个丰富的对象模型,其中包含多组聚合根

我们正在使用Castle堆栈(通过ActiveRecord单轨传输到nHibernate)

我们已经将聚合根标记为lazy
[ActiveRecord(lazy=true)]
,并在我们的存储库中定制了“渴望”例程以渴望获取对象图。我们使用HQL从根目录的子集合中定义急切获取

e、 g.如果
Account
是聚合根目录(并标记为lazy-loaded),我们将立即获取
Account。。命令。。完整图形的产品
实体

到目前为止(希望如此),没有什么意外

现在,如果在上面的示例中,Product也被标记为
[ActiveRecord(Lazy=true)]
,这似乎停止了HQL中的eager-fetch指令

是否有人知道一种方法,可以强制对延迟加载的子对象进行快速获取

干杯 伊恩

更新

好的,这里有一些hql示例,使用下面“me.yahoo.com/./1”中的示例,我们在获取多对多关系时使用IMuliQuery重新选择N+1依赖项。我们还显式地使用多对多映射类。因此,我们的hql是:

from Account a 'm eager loading the graph
inner join fetch a.AccountsOrders ao 
inner join fetch ao.Order
from Account a 'm eager loading the graph
inner join fetch a.AccountAddresses aa
inner join fetch aa.Address ad
where a.ID = ?
。。。这将执行2条sql语句并返回所需的最小行集,我们可以将其分解为单个对象图。很好

但是。。。例如,如果
Address
标记为lazy-loaded(而
Order
未标记为lazy-loaded),则访问
Order
不会触发进一步的sql语句,而访问
Address
则会触发sql语句,尽管两者都是渴望加载的

那么,为什么上面的延迟加载实体
地址
,没有通过上述语句获取呢?

对Account.Order.Product实体执行“内部连接获取”。因此,不要像这样(这可能是您已经拥有的):

告诉它去拿订单。还有产品:

"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?"

你为什么想要这种渴望的行为

ActiveRecord中的所有关系属性都有一个“Lazy=”参数,告诉ActiveRecord延迟加载相关对象。除了我以外的所有人。BelongsTo检查依赖对象的ActiveRecord属性中是否有Lazy=true,然后为该对象创建代理,而不是执行选择或联接

要使延迟加载工作,类实例的所有方法和属性都需要标记为虚拟。这允许ActiveRecord构造一个动态代理类

现在,获取完整的性能图听起来似乎是个好主意,但实际上可能较慢。我有三个很好的理由:

1.)BelongsTo有一个Fetch选项来定义如何提取相关对象。Join强制AR使用联接。获取枚举。Select强制AR对每个对象使用单独的Select语句。连接速度很慢,从切换到单个选择,我们看到性能提高了10倍。Lazy=true+FetchEnum.Select和eager在客户端代码中没有明显的区别

2.)NHibernate执行缓存。如果对象已经缓存在会话或二级缓存中,则可以从那里加载该对象,从而避免额外的工作

3.)如果没有引用对象图的一部分,则可能会错过延迟加载的任何好处。同样,你会做比必要的更多的工作。

摘自“NHibernate in Action”,第225页:

NHibernate目前限制您只获取一个收藏


这也许可以解释第二个获取地址的查询。

我大体上同意但不同意需要急切的行为。。。。当然,默认情况下,我们将惰性属性设置为对象“日常”使用所需的属性。然而,某些方法/过程是数据密集型的,因此我们获取数据的“大图”。我们所拥有的这些获取角色是根据特定的需求而形成的,并且显示出更高效(NHProf和SqlProfiler中可查看的选择频率较低)。因此,在日常对象操作中,我们当然依赖于标记。然而,对于数据量大的操作,我们将从一个候选角色获取。通过nHibernate升级解决了这个问题。为什么投票被否决?在需要快速加载的情况下,这不是一个好的解决方案吗?投票结果从-3增加到-2。
"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?"