Introduction to Entity Framework: Part IV - IQueryable
This is part four of my Entity Framework tutorial. If you have not read the previous parts of this tutorial and you do not know how to setup EF and write LINQ queries against it then please read those first.
Table of Contents
This part of the tutorial is off the beaten path a little bit but I feel that it is an important follow-up to understanding LINQ to Entities. I will write another article about Deferred Execution in another post, but for now I want to focus on IQueryable<T>
and expression trees.
What is IQueryable<T>
?
IQueryable<T>
is a special type of collection that inherits from IEnumerable
. The difference here is that when you write LINQ queries against an IQuerable
or IQueryable<T>
collection you are building an expression tree. This expression tree represents code to be executed. Because this logic is represented in an expression it can be translated to the native language of your data source, like SQL Server for instance.
Expression Trees
In order to understand IQueryable
you must first understand expression trees. Here is the definition of Expression Trees as per the MSDN:
"Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a
method call or a binary operation such as x < y.
You can compile and run code represented by expression trees. This enables dynamic modification of executable code,
the execution of LINQ queries in various databases, and the creation of dynamic queries."
It's important to realize that when you are writing queries against IQueryable
you are actually building an expression tree. This is a very powerful tool, but it brings in a few limitations. There are some things you can do in regular LINQ queries that you can't do in LINQ expressions. For one, the logic has to be completely encapsulated in the expression. This means that no calls to outside methods or delegates can be made. Lambda expressions are used to represent logic within expression trees. You cannot use regular delegates; you can't even use the lambda syntax that includes a statement body.
// This is not acceptable in an expression.
x =>
{
return x.Username;
}
// This is acceptable.
x => x.Username;
Even though those two lambda expressions essentially perform the same task, an expression cannot peer inside any statement bodies (code within curly braces). This has bitten me quite a few times when I forget that I can't just make a custom method to call from within a LINQ query.
When writing LINQ you can often find yourself writing really complicated queries. If you're like me then you like to clean up these jumbles by factoring out redundant and/or commonly used parts of the query into a method elsewhere and then call it from within the expression. This works great against normal LINQ to Objects but not so much when querying against an IQueryable
. For this you will have to create methods that return an Expression<Func<T>>
. For more details on simplifying complex LINQ expressions, see my previous blog post.