2010-12-08 42 views
8

我得到我們的生產Web服務器上顯示以下錯誤:NHibernate LazyInitializationException ..如何防止?

NHibernate.LazyInitializationException 
: 
Initializing[Domain.Entities.AudienceTypes.Region#4]-failed to lazily initialize a 
collection of role: Domain.Entities.AudienceTypes.Region.PeerGroups, 
no session or session was closed 

這是不好的。讓應用程序再次工作的唯一方法是重置IIS,這不是一個真正的選擇。這是什麼意思?我怎樣才能防止它?

回答

9

默認情況下的關係是懶惰的。這意味着僅當您訪問保存關係的屬性時纔會執行加載關係的SQL查詢。

問題是,如果您訪問一個從未被調用過的懶惰屬性,並且會話關閉,那麼您會得到該錯誤。 你必須解決方案:

  • 不要關閉會話,直到你完成
  • 之前關閉會話訪問所有以後會用到的懶惰性。
2

不要關閉會話,直到您完成對象的處理。

這是與NHIbernate IMHO一起工作的最大挑戰之一:定義會話邊界。

在ASP.NET應用程序中,它非常簡單:會話從請求開始時開始,您可以在請求結束時關閉會話。

在WinForms應用程序中,它有點困難:您必須明確定義會話何時開始以及會話何時關閉的邊界。 在WinForms應用程序中,我通常定義代表某種工作單元的「任務」。每個任務都有一個會話。會話在創建任務時創建/打開,並在任務完成時關閉。

接下來,您還可以將一些關聯定義爲非懶惰。但是,如果你這樣做,你應該確保性能不受影響。

0

除了Frederik和lujop的迴應,如果您正在開發一個ASP.NET應用程序(正如您提到的Web服務器所建議的那樣),使用依賴注入框架(如Castle Windor)是一個不錯的主意處理你的ISessions的生命週期。溫莎城堡有一個'PerWebRequest'的生活方式設置,可以爲你做到這一點。

如果不成功,請在每次請求開始時手動創建一個ISession,該請求在請求結束時被銷燬(可能會自動刷新自身)。然後你的應用程序可以使用這個ISession。

這絕對與ISession在你認爲是關閉之前關閉有關。

8

爲了避免這個問題,你需要在你的地區映射類變化如下

 
References(x => x.PeerGroupId, "PeerGroupId").Fetch.Join(); 

添加Fetch.Join的點組參考()將防止LazyInitializationException中。

+0

這是實際的答案。 – Alex 2014-12-17 11:23:18