1

I have an object that I want to eagerly load, where I want to eagerly load several parent elements, but also some grandparent elements. I've set up my select like so:

var events = (from ed in eventRepo._session.Query<EventData>() where idsAsList.Contains(ed.Id) select ed)
                            .FetchMany(ed => ed.Parents)
                            .ThenFetchMany(pa => pa.Grandparents)
                            .ThenFetch(gp => gp.GreatGrandparents)
                            // other fetches here for other attributes
                            .ToList();

My problem is that if I just .FetchMany the parents, I get the right number of elements. Once I add the grandparents, I get way too many, and that grows even more with great grandparents.

It's clearly doing some kind of cartesian product, so I had a look around and saw that some people use Transformers to solve this. I had a look at that and tried to implement it, but adding a .TransformUsing() causes a compiler error, since I don't seem to be able to call .TransformUsing() on this type of call.

What is the right way to get the right number of elements from such a call, without duplicates due to computing the cartesian product?

Jim
  • 4,509
  • 16
  • 50
  • 80

2 Answers2

0

Here is a pretty popular post that uses Futures to do this type of loadign to avoid cartesian products. It isn't as elegant as doing it in a single query but it gets the job done.

Fighting cartesian product (x-join) when using NHibernate 3.0.0

One other possible solution would be to define your collections as sets instead of bags. This would also avoid cartesian product issues. I don't really like this solution considering you have to use an nhibernate specific collection type but it is known to work.

Community
  • 1
  • 1
Cole W
  • 15,123
  • 6
  • 51
  • 85
0

There is not much you can do about it if you get force NHibernate join explicitly. The database will return same entities multiple times (this is perfectly normal since your query makes Cartesian joins). And NHibernate cannot distinguish if you ask same item multiple times or not. NHibernate does not know your intention. There is a workaround though. You can add the below line

var eventsSet = new HashSet<Events>(events);

Assuming your entity override Equals and GetHashCode, you will end up with unique events.

Onur Gumus
  • 1,389
  • 11
  • 27