3

I have an IEnumerable variable named "query" which represents an entity framework query. If I do the following, will it enumerate the query more than once? My confusion is in "result" being an IEnumerable and not a List.

IEnumerable<T> result = query.ToList(); bool test = result.Any(); 

as apposed to this:

// Using List to only enumerate the query once List<T> result = query.ToList(); bool test = result.Any(); 

Also, I know this is silly, but would it enumerate twice if I do the following, or would it somehow know that "query" was already enumerated even though the result of the enumeration is not being used?

List<T> result = query.ToList(); bool test = query.Any(); 

Thanks!

3
  • ToList() would most likely convert your IEnumerable to a List, so would iterate through it. But Any() only checks if the IEnumerable contains any elements, so it would almost sure not enumerate your result. Commented Aug 27, 2014 at 14:06
  • 1
    the 3rd version would generate two db queries, if query is an IQueryable<T> Commented Aug 27, 2014 at 14:07
  • it will enumerate the query @ query.ToList(); only Commented Aug 27, 2014 at 14:09

3 Answers 3

4

Once you're calling ToList or ToArray you will create an in-memory collection. From then on you're not dealing with the database anymore.

So even if you declare it as IEnumerable<T> it actually remains a List<T> after query.ToList().

Also, all related LINQ extension methods will check if the sequence can be casted to a collection type. You can see that for example in Enumerable.Count the Count property wil be used if possible:

public static int Count<TSource>(this IEnumerable<TSource> source) { if (source == null) throw Error.ArgumentNull("source"); ICollection<TSource> collectionoft = source as ICollection<TSource>; if (collectionoft != null) return collectionoft.Count; ICollection collection = source as ICollection; if (collection != null) return collection.Count; int count = 0; using (IEnumerator<TSource> e = source.GetEnumerator()) { checked { while (e.MoveNext()) count++; } } return count; } 

According to your last question, if it makes a difference wether or not you use the list or again the query in this code snippet:

List<T> result = query.ToList(); bool test = query.Any(); 

Yes, in this case you are not using the list in memory but the query which will then ask the database again even if .Any is not as expensive as .ToList.

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

5 Comments

Tim, OP is talking about entity framework. And also IEnumerable<T> is actually a List<T> is confusing..
@SriramSakthivel Once you call ToList you're no longer dealing with an EF query.
Tim, I wonder if discussing the optimization in Count if the collection is a list is in fact just making things more confusing, not simpler.
@Servy I know, I think tim edited the answer. My comment was before the edit.
I like the edit a lot; really makes the answer more digestible.
1

When you call ToList on your query it will be transformed into a list. The query will be evaluated right then, the items will be pulled out, and the list will be populated. From then on that List has no knowledge of the original query. No amount of manipulation of that list can in any way affect or evaluate that query, as it knows nothing about it.

It doesn't matter what you call that List, or what type of variable you stick it in, the list itself simply doesn't know anything about the IQueryable anymore. Iterating the variable holding the list multiple times will simply iterate that list multiple times.

In just the same way that the list doesn't know a thing about the query, the query doesn't know a thing about the list. It doesn't remember that it's items were put into a list and continue to return those items. (You can actually write query objects like this, in theory. It's called memoization, for the query to cache it's results when iterated and continue to provide objects from that cache when iterated later. EF doesn't memoize its queries by default, nor does it provide a tool for memoization by default, although 3rd party tools provide such extensions.) This means that the 3rd code snippet that you have will actually execute two separate database queries, not just one.

Comments

1

No the enumeration occour only in ToList().

http://msdn.microsoft.com/it-it/library/bb342261(v=vs.110).aspx

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.