Duplicates when eager fetching a reference (many-t

2019-02-13 18:29发布

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!

1条回答
Emotional °昔
2楼-- · 2019-02-13 19:26

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.

查看更多
登录 后发表回答