In the next Entity Framework, choose N+1.



The fact that EF4 struggles to handle collections that are lazily loaded is one of the few legitimate criticisms I hear of it when compared to NHibernate. On a lazy-loaded collection, for instance, if I say:

if (MyAccount.Orders.Count() > 0) ;

If it hasn't already, EF will remove the whole collection, but NH is wise enough to send out aselect count(*)

To assist with the batch fetching, NH also provides several great n + 1 issue. I believe the Include function in EF4 is the closest thing it can do to this.

Has the EF team given any hints that this will be solved in the next release? Although I am aware that POCO is receiving a lot of attention, this seems like a widespread remedy.

2/21/2011 8:25:22 PM

Accepted Answer

Your description is not a N+1 issue. Zzz-5-Zzz is an example of a N+1 problem. N+1 entails doing N+1 selections as opposed to only one (or two). Using your example, it most likely means:

// Lazy loads all N Orders in single select
foreach(var order in MyAccount.Orders)
  // Lazy loads all Items for single order => executed N times
  foreach(var orderItem in order.Items)

This can be quickly fixed by:

// Eager load all Orders and their items in single query
foreach(var order in context.Accounts.Include("Orders.Items").Where(...))

I think your example is sound. You have a collection that makes public.IEnumerable and you carry outCount performed on it. The count is carried out in memory while the collection is lazily loaded. There is just one platform where Linq queries may be converted to SQL.IQueryable with the query represented by expression trees. ButIQueryable represents query: Each access causes a new database execution, therefore, for instance, verifying the count in a loop causes a new database query to be run on each iteration.

Therefore, implementing a dynamic proxy is more important.

In Code-first CTP5 (the final version will be named EF 4.1), it is now possible to count related entities without loading them.DbContext in place ofObjectContext but not by direct contact with the collection. You must use something like:

int count = context.Entry(myAccount).Collection(a => a.Orders).Query().Count();

Query returns prepared in the methodIQueryable This, if you use lazy loading, is likely what EF does, but you may further change the query – above, I usedCount .

5/19/2015 1:07:29 PM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow