重复提取参考(多对一) [英] Duplicates when eager fetching a reference (many-to-one)

查看:144
本文介绍了重复提取参考(多对一)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,是的,我正在使用DistinctRootEntityResultTransformer。

我有以下(Fluent NHibernate)映射:
$ b $公共FirstObjectMap()
{
Id(x => x.Id):
HasMany< SecondObject>(x => x.SecondItems).KeyColumn( FirstObject_ID);

$ b $ public SecondObjectMap()
{
Id(x => x.Id).Column(ID);
引用(x => x.ThirdObject).Column(ThirdObject_ID);

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

$ b $ public FourthObjectMap()
{
Id(x => x.Id).Column(ID);

$ / code>

请注意,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 where ...);

//这是甚至不需要的,因为我在HQL
中使用不同的查询语句。

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

为了测试,我在数据库中有1个FirstObject,1个SecondObject,1个ThirdObject和24个FourthObjects。 SQL查询按预期返回了24行。



然而,下面是catch:NHibernate创建:

$ $ $ $ $ $ $ $ 1 $ FirstObject
24 SecondObject(应该是1)
24 x 1 ThirdObject(应该是1)
24 x 1 x 24 FourthObject(应该是24)



所以NH无论如何都会创建24个SecondObject而不是1个。



不知道如何映射连接提取(左或内部似乎并不重要)到引用(SecondObject中的ThirdObject的引用)。

什么是我的选择?我不能改变数据模型,但我确实需要急于加载它。



感谢您!

解决方案

独特的根实体只在加载父项和子项时才起作用。对于孙子女和孙辈,这是行不通的。问题是你正在加载多个集合关联并返回一个大的笛卡尔积



请阅读 Ayende的文章解释了为什么是这种情况和解决方法。


一些可能不会立即显示的内容将导致
笛卡尔乘积。这在文档中已经指出,但是I
认为我们都可以同意,虽然可能有这个
行为的原因,但它是远远不理想的。


First of all, yes, I am using DistinctRootEntityResultTransformer.

I have the following (Fluent NHibernate) mapping:

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");
}

Notice, that SecondObject refers to ThirdObject (meaning the key is on SecondObject).

My query looks like this:

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>();

For testing, I have 1 FirstObject, 1 SecondObject, 1 ThirdObject and 24 FourthObjects in database. The SQL query returns 24 rows as espected.

However, here's the catch: NHibernate creates:

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

So NH for whatever reason creates 24 SecondObject instead of 1.

I'm guessing it doesn't know how to map "join fetch" (left or inner doesn't seem to matter) to Reference (the reference to ThirdObject in SecondObject).

What are my options ? I can't change the data model, but I do need to eager load it all.

Thanks in advance!

解决方案

Distinct root entity only works if you load a parent and children. For grandchildren and great grandchildren this does not work. The problem is you are loading multiple collection associations and returning a large cartesian product

Please read this article by Ayende which explains why this is the case and a workaround.

Something that may not be apparent immediately is going to result in a Cartesian product. This is pointed out in the documentation, but I think that we can all agree that while there may be reasons for this behavior, it is far from ideal.

这篇关于重复提取参考(多对一)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆