3

我在我的Web應用程序中遇到nHibernate中的多對多關聯和會話問題。nHibernate多對多映射和延遲加載

我正在使用的對象始終保持它與會話之間的連接,但通過服務器進行訪問。從來沒有一個問題。到現在。我爲我的班級添加了一個新的多對多的關聯。

這裏是許多一對多映射(名稱改爲更有意義):

<bag name="ProductsToCategory" table="Tab_ProductsToCategory"" cascade="all-delete-orphan"> 
     <key column="ProductID" /> 
     <many-to-many class="CategoryClass" column="CategoryID" /> 
</bag> 

當我運行代碼,它可以在初始加載。但是隨後到訪問該對象調用服務器 - 對象保持在Web會話 - 導致此集合被打破,並拋出這個錯誤:

failed to lazily initialize a collection, no session or session was closed

奇怪。我想知道是否有什麼關於它是導致問題的多對多關聯?這個多對多隻添加到這個類,而不是添加到映射另一端的類'CategoryClass',因爲我不需要它。 該對象似乎很好,直到我添加此映射。

任何想法?

ALSO:我試着簡單地檢查對象是否不在會話中。它不是。所以我打電話給:session.refresh(productClass),一切都正確更新,包括我的麻煩映射。然而。它加載了TWICE集合中的每個項目!該集合的數量是數據庫中的兩倍,每個單項出現兩次。如果我能得到這個問題的答案,那麼前一個問題就不重要了。

如果您需要任何其他信息,請讓我知道。乾杯。

回答

5

我假設你在web應用程序中使用session-per-request模式。延遲加載要求最初用於加載父對象的會話在訪問子集合時仍處於打開狀態。您正在爲每個HTTP請求創建一個新會話,因此在第一個請求中以會話狀態存儲的對象是第二個請求中的分離對象。這就是爲什麼你會收到錯誤,以及爲什麼原始對象不在第二個請求中的會話中。

要修復它,請在從會話狀態訪問對象時調用ISession.Lock

var myProductClass = GetProductClassFromSession(); // whatever method you use to do this 
session.Lock(myProductClass, LockMode.None); 

這應該解決您的問題,但更好的方法可能是使用NHibernate的二級緩存功能,而不是會話狀態。

順便說一下,您可能不想在多對多映射中使用cascade="all-delete-orphan"。這會導致在刪除產品時刪除類別對象。