2

I'm working with entity framework with POCO objects and I've got LazyLoading turned on.

If i'm working with a collection associated with an object, when is the collection fully loaded and in what circumstances?

If I call each of these

Order.OrderItems.Count()
Order.OrderItems.Any(x => x.StatusId = aValue)
Order.OrderItems.All(x => x.StatusId = aValue)

Do any of these guarantee the complete loading of the OrderItems collection? At points in the code we are calling

Order.Include(“OrderItems”) 

when querying or

context.LoadProperty(order, “OrderItems”) 

after querying

But I’ve realised sometimes this isn’t always happening – and I want to know the consequences of this not occurring. I think I’ve got a bit of a knowledge gap with it

2 Answers 2

4

Linq methods don't generally load your data until you either foreach over their result, or append a ToList, ToArray, etc. This is how the Linq to Entities provider can allow you to chain methods and only build a query over the final structure.

If a method returns an IQueryable or IEnumerable, you can be pretty sure that Linq won't load the data at that point.

But:

Order.OrderItems.Count()
Order.OrderItems.Any(x => x.StatusId = aValue)
Order.OrderItems.All(x => x.StatusId = aValue)

For an outer-most query, if Linq must return a boolean value or an integer then it must run your query immediately. But things get a little more complicated for nested queries, since they won't be evaluated until the outer query gets evaluated.

As for:

Order.Include("OrderItems")

I believe an Include won't resolve a query on its own. You use it to piggyback additional data when you're making another query.

Linq in general

If you want to know (generally) how Linq works, you can check out this set of articles:

http://msmvps.com/blogs/jon_skeet/archive/tags/Edulinq/default.aspx

That will give you an idea of when an IEnumerable can be deferred, and when it must be evaluated. It won't tell you everything about the Linq to Entities provider, but a good portion of the knowledge will transfer.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Merlyn Morgan-Graham. Could you clarify 'if Linq must return a boolean value or an integer then it is likely to run your query immediately'. I've looked at msmvps.com/blogs/jon_skeet/archive/2010/12/28/… and it appears that Any and All actually iterate through the results under the covers so would automatically realise the collection. So it seems as if Any/All do load the collection in an outer query
@TimBrown: "it appears that Any and All actually iterate through the results under the covers so would automatically realise the collection". I think this is exactly what I said, just in weasel-speak ("likely" = always, lol). I made an edit just now that hopefully has cleared up that sentence.
Also, by nested query, I mean things like : Order.OrderItems.Where(i => i.Rebates.Any()) - the Rebates.Any() won't get evaluated unless the outer query is evaluated.
3
Order.OrderItems.Any(x => x.StatusId = aValue)
Order.OrderItems.All(x => x.StatusId = aValue)

are queries.

These queries are executed when you call .ToList() (or some other iterator to materialize it into objects). If you use .Include then included property will be populated (query will contain join for that table) when you execute query. Using Any or All (or any filter extension like Where) only adds where condition (which can be from another table), but it does not put OrderItems into sql select, so they will not be loaded unless you use .Include.

--

Not related to your question, but if you are fresh with this, and you have paging, remember to add Skip and Take to your query before calling ToList (executing query), I have seen people calling ToList very early and reading whole table to memory before doing paging.

4 Comments

+1 for the paging advice. Really? I thought people would specifically seek out things like Skip and Take when trying to implement paging..? That's the whole point of Linq, and all. Weird... :)
Well, often there is no specification, and there is "paging will not be available" directive when people make prototype. Later, that prototype becomes release and after there is xx records, there is directive to add paging as "grid takes up too much space". New developers which don't know how linq works under the hood often only add Skip/Take to the variable they have in the controller/codebehind, not being aware of that variable containing whole table. And this is the simplest of performance issues that emerge from incorrect usage of linq (imagine "subquery" in foreach loop :)).
Thanks for you comment @Goran Obradovic but your comment 'These queries are executed when you call .ToList()' seems to contradict the first answer which says that a method that returns a boolean or int would load the collection. Apologies if I have misunderstood. Is there a contradiction?
Well, I'm not completely sure about this, but if you call '.Count' you will certainly execute query, but that query does not load all items, it executes count (rowcount) in sql and returns that value (it does not have much sense to copy all to memory just to count it). If you want to be sure, you can always start Visual Studio profiler and check "Tier interactions" (I think it is called something like that). That will enable you to see sql queries that your application sends to sql server (and to see many other usefull things like where you may want to optimize your code first :))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.