Using LINQ, Lambda and Expression Trees in .net

LINQ and Expression Trees

Expression Trees represent code in a tree-like data structure.  In LINQ, expression trees represent structured queries that target sources of data that implement IQueryable<T>.  For example, LINQ to SQL provider implements the IQueryable<T> interface, wherein during run-time, when a LINQ to SQL query is executed the underlying implementation leverages the Expression Tree to convert the LINQ query to a “tree like data structure” and then constructs the required output (which in this case is the SQL query), i.e., translate it into a query language appropriate for the data source.  However, on the contrary, when we use LINQ queries to filter data from objects, it returns an IEnumerable<T> which doesn’t use Expression Trees internally.  For instance if you look at the below IEnumerable<T> interface definition,it doesn’t have an Expression defined in it.

Hence it proves that LINQ queries that return an IEnumerable doesn’t internally leverage the Expression as it gets parsed and executed within the same process (unline LINQ TO SQL where the LINQ needs to be translated to a SQL query and the query itself needs to be passed as a string to SQL Server for execution).

    public interface IEnumerable<out T> : IEnumerable
    {
        IEnumerator<T> GetEnumerator();
    }

On the contrary, if we look at the IQueryable interface (the highlighted row), the Expression property is defined which indicates that data sources that implement IQueryable<T> (such as LINQ to SQL) that needs to construct Expression trees by translating the LINQ to SQL query and for that they would construct Expression tree for the sake of analyzing/parsing the tree node and generate the output SQL

    public interface IQueryable : IEnumerable
    {
        Type ElementType { get; }
        Expression Expression { get; }
        IQueryProvider Provider { get; }
    }

Before we further take a deep dive on Lambda expressions, its imperative to know that Lambda’s are of two types:

Expression Lambda –  Such type of Lambda’s are always represented in a single line.  For E.g,,

Func<int, int, int, int> funcAdd = (a, b, c) => a + b;

Statement Lambda – Support multi-line statements and are always enclosed within curly braces.  (Statement Lambda’s or multi-line Lambda’s are not supported by Expression trees)

Func<int, string> add = x => {
	x = x + 5;
	return string.Format("The computed value is {0}", x); 
};

Use of Lambda’s in LINQ Queries:

LINQ queries when used in code can be leveraged either by using Query Syntax or method syntax for querying/filtering data from data sources.  Even though they both are semantically identical, method syntax uses Lambda expressions and may appear to be a bit complex to understand.  For instance the below is an example of using the easy-to-understand LINQ Query Syntax :

int[] numbers = { 5, 10, 8, 3, 6, 12};

        //Query syntax:
        IEnumerable<int> numResult = 
            from num in numbers
            where num > 10
            orderby num
            select num;

However, in Method syntax, we can achieve the same result by employing Func Lambda Generic Delegates :

int[] numbers = { 5, 10, 8, 3, 6, 12};

IEnumerable<int> numResult  = numbers.Where(num => num > 10).OrderBy(n => n);

What is Expression Tree?

According to MSDN an Expression tree :

  1. Represents code in a tree-like data structure, where each node is an expression.
  2. Offers the ability to compile and run code represented by expression trees that allows dynamic modification of executable code (such as execution of LINQ queries in various databases by creating dynamic queries.
  3. Can also be used in DLR (Dynamic Language Runtime) to provide interoperability between .net and dynamic languages.

Creating/Defining Expression Tree

When a lambda expression is assigned to a variable of type Expression<TDelegate>, the compiler emits code to build an expression tree that represents the lambda expression.  Note that it works only with Expression lambda (single line lambdas) and not with statement lambdas (multi-line lambda).

Expression<Func<int, int, int>> funcAdd = (a, b) => a + b;

 

Good Sources for Learning LINQ, Lambda and Expression Trees:

  • https://msdn.microsoft.com/en-us/library/bb882637.aspx
  • https://msdn.microsoft.com/en-us/library/bb397951.aspx

1,934 total views, 1 views today

0 votes

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha *