I know of several LINQ statements that will cause EF to evaluate and return results form the DB to memory. .ToList()
is one. Does anyone have a comprehensive list of the statements that do this?
Not sure of...
.SingleOrDefault()
.Union()
EDIT: Wish I could accept all these answers. Great info from everyone!
By default, LINQ queries return a list of objects as an anonymous type. You can also specify that a query return a list of a specific type by using the Select clause.
LINQ to Entities provides Language-Integrated Query (LINQ) support that enables developers to write queries against the Entity Framework conceptual model using Visual Basic or Visual C#. Queries against the Entity Framework are represented by command tree queries, which execute against the object context.
Here, you will see an overview of how entity framework works. Entity Framework API (EF6 & EF Core) includes the ability to map domain (entity) classes to the database schema, translate & execute LINQ queries to SQL, track changes occurred on entities during their lifetime, and save changes to the database.
This fact means it can be queried with LINQ. A query is executed in a foreach statement, and foreach requires IEnumerable or IEnumerable<T>. Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T> are called queryable types.
It's a long list. They boil down to
Aggregate
All<TSource>
Any
Average
Contains
Count
ElementAt<TSource>
ElementAtOrDefault<TSource>
Empty<TResult>
First
FirstOrDefault
Last
LastOrDefault
LongCount
Max
Min
SequenceEqual
Single
SingleOrDefault
Sum
ToArray<TSource>
ToDictionary
ToList<TSource>
ToLookup
The rest are either Deferred Streaming Execution or Deferred Non-Streaming Execution.
In light of your question, SingleOrDefault()
is Immediate Execution and Union()
is Deferred Streaming Execution.
Anything that returns a concrete object or data structure (Count
, Sum
Single
, First
, ToList
, ToArray
, etc.) is evaluated immediately, so SingleOrDefault
certainly does.
Anything that returns an IQueryable<T>
(Select
, GroupBy
, Take
) will be deferred (so that operations can be chained), so Queryable.Union
will be deferred.
Anything that returns an IEnumerable<T>
will also be deferred, but subsequent queries will be done in Linq-to-objects, so subsequent operations won't be translated to SQL. (Empty
is an exception since there's not really anything to defer - it just returns an empty collection)
From MSDN,
Queries that perform aggregation functions over a range of source elements must first iterate over those elements.
Examples of such queries are Count, Max, Average, and First. These execute without an explicit foreach statement because the query itself must use foreach in order to return a result.
Note also that these types of queries return a single value, not an IEnumerable collection.
To force immediate execution of any query and cache its results, you can call the ToList<TSource> or ToArray<TSource> methods.
In the case of Entity Framework, there's an easy way to refresh your memory.
Entity Framework has Async
variants of all such methods defined in System.Data.Entity
, because Async
doesn't make sense with the others as it's the very act of querying the database that the Async
variants do asynchronously.
So if there's an Async
variant, then it hits the database and otherwise it does not.
Enumerating or producing an IEnumerable<T>
is a part-way case though: The act of obtaining an IEnumerable<T>
obtaining its enumerator (as happens at the start of foreach
blocks) does not hit the database, but the first MoveNext()
(which happens immediately within the foreach
does hit the database, and it then continues to stream from the resultset until either MoveNext()
returns false (as when the foreach
reaches a "natural" end) or the enumerator is disposed prior to that (as when the foreach
is aborted).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With