2012-04-17 26 views
1

我們遇到了一個工作問題。當我們嘗試從MVC3視圖中訪問NHibernate實體上的惰性加載屬性時,將拋出「No Session」LazyInitializationException。這只是在上週纔開始出現,但我們無法縮小這個問題的範圍。雖然看起來並不是簡單的解決方案。MVC3視圖中的惰性加載NHibernate實體

注意

  • 堆棧跟蹤的例子:http://textsnip.com/613608
  • 我們不要處理掉(或包裹會話中使用)在我們的項目中的任何地方。我們讓ObjectFactory來處理它。
  • 這個只有在我們的TeamCity測試環境中運行迴歸測試時發生(SpecFlow與WatiN)。我們沒有人能夠在我們的開發機器上重現這個問題。
  • 這也不會一致發生。雖然失敗的測試通常是相同的測試,但它們並不會一直失敗。訪問會碰到某些相同視圖的頁面的其他測試不會失敗。
  • 在確實失敗的測試中,它們看起來比懶惰的加載集合初始化更重於非集合初始化,但都發生了。
  • 儘管我知道只要有可能,只要有可能加載實體,由於許多表模型的相互依賴關係,它會更好,但目前並不可行。

我們在這裏錯過了什麼?

+0

你可以發佈實體和nhibernate標準/查詢等? – Mariusz 2012-04-19 16:42:56

+0

你在測試中如何管理ISession? – dotjoe 2012-07-31 19:22:34

回答

0

你是否直接綁定到你的視圖中的對象模型?這聽起來像你的問題,因爲你直接查看綁定到域對象。由於域對象具有延遲集合,因此它正嘗試按需加載集合元素,這需要一個Nhibernate會話。

您應該在控制器方法中構建完整視圖模型。

我的建議是爲每個視圖創建一個視圖模型。然後,當您查詢NHibernate時,直接投影到模型中或使用Automapper將您的對象模型轉換爲視圖模型。直接投影的好處在於,通過nhibernate的查詢將更加高效,因爲它只會選擇您需要的列。

另請參閱此文章。 http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

這是一組創建視圖模型的最佳實踐。

+0

我們很清楚,試圖在視圖中使用我們的實際實體被認爲是否定的,但我們目前無法改變這種情況。此外,這個問題最近剛剛開始出現,當它幾個月工作正常。我們知道我們需要NHibernate會話,這就是爲什麼我們讓ObjectFactory在每個請求的基礎上創建它,所以當模型在視圖中使用時它應該仍然存在。 – rossisdead 2012-04-18 16:26:04

1

您的實體加載模式在視圖中稱爲打開會話,它被認爲是反模式。更多關於這種模式的缺點herehere

推薦的方法是使用一些預取數據的視圖模型。但是如果你不能這樣做,你可以使用linq預取模型數據來擴展nhibernate。有一個開源庫ITDT.Sentia,它提供了輸入擴展擴展,或者你可以在谷歌搜索「nhibernate擴展」。對於更低層次的東西,你可以看看nhibernate fetching strategies

例如使用ITDT。Sentia庫,並具有以下型號:

public class User : BaseEntity 
{ 
    public virtual string Email { get; set; } 
    public virtual Company Company { get; set; } 
} 

public class Company : BaseEntity 
{ 
    public virtual string Name { get; set; } 
} 

並獲取用戶後,假設公司實體的延遲加載,你可以這樣做:

IList<User> users = userRepository 
    .GetAll() 
    .Where(u => /*some constraints*/) 
// here you are telling nhibernate to make a join and eger load what you need 
    .Expand(u => u.Company) 
    .ToList(); 

至於在開發環境我只能猜測不同的行爲它以某種方式使用其他配置文件,也許有不同的調試/發佈web.configs?