2011-12-07 121 views
2

我正在讀這篇文章NHibernate的延遲加載http://nhforge.org/wikis/howtonh/lazy-loading-eager-loading.aspx,它使用和實施例的一類結構類似這樣的:NHibernate的延遲加載行爲

Class Diagram

的製品然後顯示如下代碼:

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個塞萊ct聲明的問題。如果我們在加載訂單後訪問訂單行項目 ,我們將爲我們訪問的每行 項目生成select語句。

這是我remebered延遲加載的特性,即當我第一次拿到訂單,訂單行收集的訂單行集合的代理,然後我通過命令行迭代每一個被加載一經請求。

但是,這不是我正在觀察的行爲。什麼時候我嘗試這在我的應用情況是,當我得到足夠確保訂單的訂單行的集合是一個代理,但只要我訪問使用第一訂單行:

fromDb.OrderLines.First() 

整個集合是裝進入記憶。這對我來說是一個問題,因爲集合包含很多項目,我只想更改一個項目,但是如果將所有項目加載到內存中並更改內存並嘗試保存順序,我顯然會獲得非常差的性能。

自從寫這篇文章以來,行爲變化了嗎?我只是誤解延遲加載是如何工作的?或者有什麼辦法可以配置NHibernate只加載它需要的集合中的項目?

回答

4

「n + 1 select語句問題。如果我們在加載訂單後訪問訂單行項目,我們爲每個我們訪問的行項目生成一個select語句。」不是正確的。訂單行全部加載在一起,因爲這在大多數情況下效率更高。選擇N + 1主要是這樣的代碼:

var orders = session.QueryOver<Order>().List() 

var usersWithOrders = orders.Select(o => o.User); 

,因爲你有1選擇的訂單和N選擇爲每個用戶(在現實中只針對不同的用戶,因爲會話緩存)

如果你知道你有大量的集合,只想處理一些或需要計數和包含,然後有<bag lazy="extra">/HasMany(x => x.Lines).ExtraLazyLoad()這會導致集合代理髮出查詢Count,Contains,this []而不是全部加載它。

或者您可以session.QueryOver<OderLines>().Where(line => line.Order == order && ...)獲取您想要處理的具體行