Thursday, 22 October 2009

Expression Trees

In LINQ, expression trees represent structured queries that target sources of data that implement IQueryable<T>. Expression trees are also used in LINQ to represent lambda expressions that are assigned to variables of type Expression<TDelegate>.
Instances of Expression<TDelegate> can be executed. To execute an expression tree call the Compile method to create an executable delegate and then call invoke it. Executing an expression tree may return a value, or it may just perform an action such as calling a method.
We can use the Expression Trees to create data store agnostic dynamic query APIs.
The foundation of the Expression Trees in .Net is the System.Linq.Expression namespace. The MSDN documentation states:
“Expression trees represent language-level code in the form of data. The data is stored in a tree-shaped structure. Each node in the expression tree represents an expression, for example a method call or a binary operation such as x < y.”
See http://msdn.microsoft.com/en-us/library/bb397951.aspx
Expression nodes are encapsulated by instances of the Expression class and its subclasses. To build expression tree nodes you use static factory methods on the Expression classes.
You can also get the compiler to build an expression tree for you from a lambda expression. When you do this the Expression is always of type Expression<TDelegate>. The Expression<TDelegate> type provides the Compile method, that compiles the code represented by the expression tree into an executable delegate.
Expression trees are immutable so if you want to modify an expression tree, you must create a copy with the necessary modifications. You can use an expression tree visitor to traverse the existing expression tree. See http://msdn.microsoft.com/en-us/library/bb882521.aspx for an example on how to do this.
Note:
“Only those expression trees that represent functions, namely Expression<TDelegate> and its parent type LambdaExpression, can be compiled into executable code. To execute other types of expression trees, you must first wrap them in a LambdaExpression node. You can obtain such a LambdaExpression by calling the Lambda method and passing the expression tree as the argument.”

Dynamic Queries

For basic information on creating dynamic queries see http://msdn.microsoft.com/en-us/library/bb882637.aspx.
For an example of using AND/OR operations see http://msdn.microsoft.com/en-us/library/bb546136.aspx.