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