1

I was reading this answer and I realized that I'm not clear on how eager loading works in the in-memory lifecycle of an IQueryable.

Say you have db.Customers.Include("Orders"), which generates an object graph like this:

Customer
   Order
   Order
   Order

If you don't enumerate the return from an Include does it load the data in-memory?

That is, does

IQueryable<Customer> customersWithOrders = db.Customers.Include("Orders");

imply that the Customer collection (and his Orders) has been brought in-memory by the eagerly includedOrders? Or, does "eagerness" mean that if/when the Customer collection is enumerated, the orders will be brought in-memory as well?

Community
  • 1
  • 1
seebiscuit
  • 4,905
  • 5
  • 31
  • 47

2 Answers2

2

Eager Loading only modifies the underlying query. That's also why you can chain multiple Include() calls (as well as other LINQ calls that rely on the deferred-execution nature of LINQ).

Only upon enumeration will the data be explicitly requested from the data-source.

Update (as per @Ehsan Sajjad comment):

With Lazy-Loading, even when the query has already been materialized (using a foreach or ToList() for example), the navigation-property (Order in this case) will only be requested from the data-source upon accessing it.

haim770
  • 48,394
  • 7
  • 105
  • 133
2

There's two things going on here. First, no query is submitted to the database until some operation is done that requires execution of that query. For example, if you were to do something like:

var foos = db.Foos.Where(...);

No query has actually been issued yet. However, if you were to then do something like:

foreach (var foo in foos)
{
    ...
}

Then, the query is sent to the database. Other things that will cause the query to be executed are things like calling ToList(), Count(), etc. Basically, whenever there's a need for the actual data, then, and only then does Entity Framework send the query.

Then, there's the totally separate concept of eager vs lazy loading. This is about related items and is basically about whether Entity Framework should issue one or more joins as part of the query or not. By using Include(), you're instructing Entity Framework to issue a join for that relationship. Again, no query will be issued until it is evaluated (iteration, enumeration, count, etc.), but when you do evaluated it, the both the set of entities and related entities you included will all be pull at once.

If you choose to not include a relationship, then you fallback to lazy-loading, which means the relationship will not be materialized unless you access it in some way. This is similar in some respects to how the initial query worked. The related items are only fetched at the point where the data is actually needed; otherwise no query is issued. However, this will then be an entirely separate query.

Long and short, you just need to pay attention to what data you need and when. If you're going to utilize related entities, then you should include those before the query is evaluated, but either way, the query will only be sent when the data it represents is necessary.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444