Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicates when eager fetching a reference (many-to-one)

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!

like image 453
user315648 Avatar asked Apr 25 '12 16:04

user315648


1 Answers

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.

like image 66
Rippo Avatar answered Nov 20 '22 01:11

Rippo