NHibernate supports the concept of eager fetching for a long time. However there are some things to consider when you start using this with the out-of-the-box NHibernate Linq provider.
Let’s first look at the obvious way:
This will return the customer and all the customer’s orders in a single SQL statement.
But this will work fine:
But if you use ‘FetchMany’ and ‘ThenFetchMany’ it will work fine:
Let’s first look at the obvious way:
var customers = session .Query<Customer>() .Fetch(c => c.Orders) .ToList();
This will return the customer and all the customer’s orders in a single SQL statement.
Rule #1: Fetch() statements must always come last.
If you want to mix Fetch with other clauses, Fetch must always come last. The following statement will throw an exception:var customers = session .Query<Customer>() .Fetch(c => c.Orders) .Where(c => c.CustomerId == "ABC") .ToList();
But this will work fine:
var customers = session .Query<Customer>() .Where(c => c.CustomerId == "ABC") .Fetch(c => c.Orders) .ToList();
Rule #2: Don’t fetch multiple collection properties at the same time.
Be careful not to eagerly fetch multiple collection properties at the same time. The following statement will execute a Cartesian product query against the database, so the total number of rows returned will be the total Subordinates times the total orders.var employees = session .Query<Employee>() .Fetch(e => e.Subordinates) .Fetch(e => e.Orders) .ToList();
Rule #3: Fetch grandchild collections using FetchMany.
You can fetch grandchild collections too. The following statement will throw an exception:var customers = session .Query<Customer>() .Fetch(c => c.Orders) .Fetch(c => c.Orders.OrderLines) .ToList();
But if you use ‘FetchMany’ and ‘ThenFetchMany’ it will work fine:
var customers = session .Query<Customer>() .FetchMany(c => c.Orders) .ThenFetchMany(o => o.OrderLines) .ToList();