I found 2 similar questions:
- Multiple Fetches in linq to nhibernate
- Is this the right way of using ThenFetch() to load multiple collections?
According to this page:
Be careful not to eagerly fetch
multiple collection properties at the
same time. Although this statement
will work fine:var employees = session.Query<Employee>() .Fetch(e => e.Subordinates) .Fetch(e => e.Orders).ToList();
It executes a Cartesian product query
against the database, so the total
number of rows returned will be the
total Subordinates times the total
orders.
Lets say I have the following model:
public class Person
{
public virtual int Id { get; private set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Article> Articles { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
What is the simplest way to eagerly load all persons with their Books, Articles, and Addresses using QueryOver/Linq (without returning a Cartesian product)?
Thanks
Update:
See cremor's answer below and Florian Lim's answer in this thread. The following code works nicely, only one round-trip to the database.
var persons = session.QueryOver<Person>()
.Future<Person>();
var persons2 = session.QueryOver<Person>()
.Fetch(x => x.Books).Eager
.Future<Person>();
var persons3 = session.QueryOver<Person>()
.Fetch(x => x.Articles).Eager
.Future<Person>();
var persons4 = session.QueryOver<Person>()
.Fetch(x => x.Addresses).Eager
.Future<Person>();
Best Answer
I prefer to use the linq provider if at all possible especially if you are using newer versions of nhibernate (>= 4.0). As long as you have your collections mapped as ISets (requires .net framework >= 4) which we converted to such that we could do eager loading and avoid cartesian products. I feel like this isn't something that is heavily advertised but I prefer this method where applicable over anything else :
If you have your collections defined like the above then you can do the following and still avoid cartesian product issues: