NHibernate延迟加载行为 [英] NHibernate Lazy Loading Behaviour
问题描述
我正在阅读有关Nhibernate延迟加载的文章 http://nhforge.org/wikis/howtonh/lazy-loading-eager-loading.aspx ,它使用这样的类结构的示例:
I was reading this article on Nhibernate Lazy Loading http://nhforge.org/wikis/howtonh/lazy-loading-eager-loading.aspx and it uses and example of a class structure like this:
文章然后显示以下代码:
The article then shows the following code:
using (ISession session = SessionFactory.OpenSession())
{
var fromDb = session.Get<Order>(_order.Id);
int sum = 0;
foreach (var line in fromDb.OrderLines)
{
// just some dummy code to force loading of order line
sum += line.Amount;
}
}
然后继续讨论:
第n + 1条选择语句问题.如果我们访问订单项 加载订单后,我们为每一行生成一条select语句 我们访问的项目.
the n+1 select statements problem. If we access the order line items after loading the order we generate a select statement for each line item we access.
这是我延迟加载的行为,即当我第一次获得订单时,订单行集合是订单行集合的代理,然后当我遍历订单行时按需加载每个行.
This is the behaviour I remebered of lazy loading, namely when I first get an order, the order lines collection is a proxy of a collection of order lines, then as I iterate through the order lines each one is loaded on demand.
但是,这不是我正在观察的行为.当我在应用程序中尝试此操作时,会发生以下情况:当我获得足够确定的订单时,订单行的集合就是代理,但是一旦我使用以下命令访问了第一个OrderLine:
However this is not the behaviour I am observing. What happens when I try this in my application is that when I get an order sure enough the collection of order lines is a proxy, but as soon as I access the first OrderLine using:
fromDb.OrderLines.First()
整个集合被加载到内存中.这对我来说是个问题,因为集合包含很多项目,我只想更改一个项目,但是如果我将所有项目加载到内存中并更改一个项目并尝试保存订单,那么我的性能显然会很差.
The entire collection is loaded into memory. This is a problem for me as the collection contains a lot of items and I only want to change one, but if I load all the items into memory and change one and try to save order I am obviously getting very poor performance.
自从撰写本文以来,行为是否发生了变化?我只是误解了延迟加载的工作原理?还是有某种方法可以将NHibernate配置为仅从所需的集合中加载项目?
So did the behaviour change since I this article was written? I am simply misunderstanding how lazy loading works? Or is there some way I can configure NHibernate to only load the items from the collection it needs?
推荐答案
"n + 1个select语句问题.如果我们在加载订单后访问订单行项目,则会为我们访问的每个订单项生成一个select语句."不是核心.订单行都被一起加载,因为这在大多数情况下效率更高.选择N + 1主要是这样的代码:
"the n+1 select statements problem. If we access the order line items after loading the order we generate a select statement for each line item we access." is not corect. The Order lines are all loaded together because this is most of the time much more efficient. Select N+1 is mostly code like this:
var orders = session.QueryOver<Order>().List()
var usersWithOrders = orders.Select(o => o.User);
因为您有1个订单"选择和N个每个用户"选择(实际上,由于会话缓存,仅针对不同的用户)
because you have 1 Select for the Orders and N Selects for each user (in reality only for distinct users because of session cache)
如果您知道您有大量馆藏,而只想处理一些馆藏或需要计数并包含,则有<bag lazy="extra">
/HasMany(x => x.Lines).ExtraLazyLoad()
会导致收集代理发出对计数,包含,此[]的查询全部加载.
If you know you have large collections and only want to process some or need Count and Contains then there is <bag lazy="extra">
/ HasMany(x => x.Lines).ExtraLazyLoad()
which results in a collection proxy that issues queries for Count, Contains, this[] instead of loading it all.
或者您可以session.QueryOver<OderLines>().Where(line => line.Order == order && ...)
获取要处理的特定行
Or you can session.QueryOver<OderLines>().Where(line => line.Order == order && ...)
to get the specific lines you want to process
这篇关于NHibernate延迟加载行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!