2014-12-31 84 views
3

我想獲得一個根實體,並渴望獲取它的子實體。但是因爲我使用NHibernate的IStatelessSession,它會爲每個子項返回根實體的重複項。使用ISession,它將解決與NHibernate的iStatelessSession返回重複的父實例急於獲取

.TransformUsing(new DistinctRootEntityResultTransformer()) 

但是,對於IStatelessSession它不是。

基本上它是關於下面的代碼,其中只有一個父實例,持有3個孩子。

var result = session.QueryOver<Parent>() 
.Fetch(i => i.Childs).Eager(); 

這將返回3個Parent的重複實例,而不是一個。有沒有人有這個解決方案?

+0

如果你保持你的childerns ISet而不是IList,這個問題不會出現 – harishr

回答

2

我會說:做不是使用StatelessSession。它不適合這個用例。

13.2. The StatelessSession interface

或者,NHibernate的提供了一個面向命令的API,它可用於流傳輸數據和從在分離對象的形式的數據庫。 IStatelessSession沒有與其關聯的持久性上下文,並且不提供許多更高級別的生命週期語義。 特別是,無狀態會話不會實現一級緩存,也不會與任何二級或查詢緩存進行交互。它沒有實現事務性的後寫或自動髒檢查。使用無狀態會話執行的操作不會級聯到關聯的實例。 集合被無狀態會話忽略。通過無狀態會話旁路NHibernate的事件模型,並進行攔截操作 ...

我只是想說明的是這裏:NHibernate: Select one to Many Left Join - Take X latest from Parent,這裏的問題是,你的連接是造成這種SQL結果,這是不適合尋呼(你遲早需要)

PARENT1 CHILD1 
PARENT1 CHILD2 
PARENT1 CHILD3 
PARENT2 CHILD4 
PARENT2 CHILD5 // if we would take 5 records, the parent2 won't get child6 
PARENT2 CHILD6 

所以這個結果是不是要走的路。我強烈建議:使用

  • 標準會話,使用isnide(讓它立刻處理)
  • 負載根實體(父)和
  • 名單
  • 讓NHibernate的懶洋洋地加載自己的孩子 - 在分開SQL查詢。

查詢可以/應該是這樣的:

ISessionFactory factory = ...; 
using (var session = factory.OpenSession()) 
{ 
    var list = session.QueryOver<Parent>() 
    .Skip(100) 
    .Take(25) 
    .List<Parent>(); 

    list.Last() // this will load all occupations at once 
     .Childs // if batch-size is higher than page size 
     .Any(); // otherwise touch more items 

} // session is closed and disposed 

作爲上述代碼段示出了,爲了避免1個+ N問題,我們必須使用的智能映射特徵中的一個:

19.1.5. Using batch fetching

NHibernate的能有效地使用批量抓取的,即,可以NHibernate的載入其他未代理如果一個訪問代理(或山口ctions。批量抓取是對懶惰選擇抓取策略的優化。有兩種方法可以調整批次抓取:在課程和集合級別上。

類/實體的批量抓取更容易理解。假設你在運行時有以下情況:你有一個ISession中加載了25個Cat實例,每個Cat都有一個對它的Owner,一個Person的引用。 Person類映射了一個代理,lazy =「true」。如果你必須遍歷整個cats集合,並呼籲cat.Owner每個,NHibernate的默認情況下將執行25個SELECT查詢,檢索owner的代理...

和父映射應該是這樣的:

HasMany(x => x.Childs) 
    ... 
    .BatchSize(100) // should be at least 25 

請,還要檢查這些:

注:有些人可能會建議你使用結果Transforemer,因爲你已經盡力了。這個解決方案可以工作,但是在C#中,在內存中完成,所以所有數據都被加載(多行),然後縮小。我永遠不會使用它。檢查:Criteria.DISTINCT_ROOT_ENTITY vs Projections.distinct