Select N+1 in next Entity Framework

后端 未结 1 624
刺人心
刺人心 2020-12-08 03:45

One of the few valid complaints I hear about EF4 vis-a-vis NHibernate is that EF4 is poor at handling lazily loaded collections. For example, on a lazily-loaded collection,

相关标签:
1条回答
  • 2020-12-08 04:12

    What you describe is not N+1 problem. The example of N+1 problem is here. N+1 means that you execute N+1 selects instead of one (or two). In your example it would most probably mean:

    // 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 is easily solved by:

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

    Your example looks valid to me. You have collection which exposes IEnumerable and you execute Count operation on it. Collection is lazy loaded and count is executed in memory. The ability for translation Linq query to SQL is available only on IQueryable with expression trees representing the query. But IQueryable represents query = each access means new execution in DB so for example checking Count in loop will execute a DB query in each iteration.

    So it is more about implementation of dynamic proxy.


    Counting related entities without loading them will is already possible in Code-first CTP5 (final release will be called EF 4.1) when using DbContext instead of ObjectContext but not by direct interaction with collection. You will have to use something like:

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

    Query method returns prepared IQueryable which is probably what EF runs if you use lazy loading but you can further modify query - here I used Count.

    0 讨论(0)
提交回复
热议问题