6

首先,是的,我正在使用DistinctRootEntityResultTransformer。渴望獲取引用(多對一)時複製

我有以下(功能NHibernate)映射:

public FirstObjectMap() 
{ 
    Id(x => x.Id): 
    HasMany<SecondObject>(x => x.SecondItems).KeyColumn("FirstObject_ID"); 
} 

public SecondObjectMap() 
{ 
    Id(x => x.Id).Column("ID"); 
    References(x => x.ThirdObject).Column("ThirdObject_ID"); 
} 

public ThirdObjectMap() 
{ 
    Id(x => x.Id).Column("ID"); 
    HasMany<D>(x => x.FourthItems).KeyColumn("ThirdObject_ID"); 
} 

public FourthObjectMap() 
{ 
    Id(x => x.Id).Column("ID"); 
} 

通知,即SecondObject指ThirdObject(意味着鍵是上SecondObject)。

我的查詢看起來是這樣的:

var query = session.CreateQuery("select distinct first from " + 
    "FirstObject as first " + 
    "left join fetch first.SecondItems as second " + 
    "left join fetch second.ThirdObject as third " + 
    "left join fetch third.FourthItems as four where ..."); 

// This is not even needed as I'm using distinct in HQL 
query.SetResultTransformer(new DistinctRootEntityResultTransformer()); 

var results = query.List<ReinsurableObject>(); 

爲了測試,我有1 FirstObject,1 SecondObject,1 ThirdObject和數據庫24個FourthObjects。按照預期,SQL查詢返回24行。

然而,這裏的漁獲:NHibernate的創建:

1 FirstObject 
    24 SecondObject (should be 1) 
    24 x 1 ThirdObject (should be 1) 
     24 x 1 x 24 FourthObject (should be 24) 

所以NH不管是什麼原因造成的24 secondObject的,而不是1

我猜它不知道如何映射「加盟提取「(左或內部似乎並不重要)引用(SecondObject中的ThirdObject的引用)。

我有什麼選擇?我無法更改數據模型,但我確實需要全部加載。

在此先感謝!

回答

4

獨特的根實體僅適用於加載父項和子項的情況。對於孫子女和孫輩,這是行不通的。問題是您正在加載多個收集關聯並返回一個大的cartesian product

請閱讀此article by Ayende,它解釋了爲什麼會出現這種情況和解決方法。

某些可能不會立即顯現的內容將導致產生 笛卡爾積。這指出了documentation,但我 認爲我們都同意,而有可能是這個 行爲的原因,這是很不理想。

+1

據我所知,Cartesian產品只在加入平行關聯時出現。例如,如果A具有B1和B2,那麼這將導致笛卡爾乘積。 Ayende在他的博客中展示了這種情況(來自Blog b左連接獲取b.Posts左連接獲取b.Users)。 但是,如果A,B,C,D是分層的(就像我一樣),他們不應該創建笛卡爾積。我面臨的問題是我有多對一,多對一,一對多,多對一的層次結構。 對不對? – user315648 2012-04-25 17:12:01

+0

不,我不相信這是正確的,你正在加載許多 - >一個 - >很多 - >一個。看看生成的SQL並運行此針對數據庫,看看發生了什麼 – Rippo 2012-04-25 17:17:17

+0

其第3至第4的關係,這是造成多個集合關聯,因此創建24秒對象 – Rippo 2012-04-25 17:23:54