LINQ to Objects series (4) Expression Tree

Source: Internet
Author: User

To further deepen our understanding of Lambda expressions, We need to master a new knowledge. The Lambda Expression Tree may look very deep and hard to understand, but in fact, it is not as difficult as you think. In this article, I would like to summarize the following points.

1. Expression Tree syntax

2. convert code to data

3. Exploration Expression Tree

4. convert data to code

5. IQueryable <T> and Expression Tree

6. Why do I need to convert a query expression from LINQ to SQL into an Expression Tree?

7. IQueryable <T> and IEnumerable <T>

8. Summary

Expression Tree syntax
// Use Lambda expressions to define a Func delegate Func <int, int, int> function = (a, B) => a + B;

The variable function points to the native executable code of adding two numbers. The above Lambda expression is equivalent to the following method.

public int function(int a, int b){    return a + b;}

This Lambda expression and this method can both be called in this way.

Int c = function (); // The result is: 3.
Convert code to data

The expression tree is not an executable code, but a data structure. So how can I convert a Lambda expression into an Expression Tree?

We can use the Expression class under the namespace System. Linq. Expressions to implement this requirement.

For example, we first create an Expression Tree, the following code.

// Create Expression Tree expression <Func <int, int, int> Expression = (a, B) => a + B;

In this way, we create an Expression Tree of Type expression <T>, which identifies Expression as not executable code; it is a data structure named expression Tree. We can use toolsExpressionTreeVisualizerTo browse the Expression Tree, such.

Exploration Expression Tree

The Expression <TDelegate> class has four attributes:

  • Body: Obtain the subject of the expression.
  • Parameters: Obtain the lambda expression parameters.
  • NodeType: GetExpressionType. A total of 45 different values, including all expression nodes of various possible types, such as return constants, such as return parameters, such as taking a small value of two values (<), for example, take the values of the two values, for example, add the values (+), and so on.
  • Type: Obtain a static type of the expression. In this example, the expression type isFunc<Int,Int,Int>.

How can we view the parameter names in the Expression Tree? We can see that the parameter is a ReadOnlyCollection set, so we can access it through indexes. The following code.

// Access the parameter Console of the Expression Tree. writeLine ("parameter 1: {0}, parameter 2: {1}", expression. parameters [0], expression. parameters [1]);

Next, how can we view the Body of the Expression Tree? In this example, it is (a + B ). The Code is as follows.

// Access the BodyBinaryExpression body = expression in the expression tree. body as BinaryExpression; ParameterExpression left = body. left as ParameterExpression; ParameterExpression right = body. right as ParameterExpression; Console. writeLine (expression. body); Console. writeLine ("expression left part:" + "{0} {4} node type: {1} {4} expression right part: {2} {4} type: {3} {4} ", left. name, body. nodeType, right. name, body. type, Environment. newLine );

Output result:

By exploring the expression tree, we can analyze each part of the expression to find its composition. As you can see, all elements of our expressions are displayed as data structures such as nodes. The expression tree is the data converted from code.

Convert data to code

We can convert code into data, so we can also convert data into code. The following code illustrates how to convert data (expression tree data structure) into code.

// Convert the data (expression Tree) to the Code int result = expression. Compile (); Console. WriteLine (result); // The output result is: 3

It can be found that the program output result is the same as the Lambda expression execution result.

IQueryable <T> and Expression Tree

Now you have at least an abstract concept to understand the Expression Tree. Now it is time to come back to understand its key role in LINQ, especially in the connection to SQL. Take some time to consider this standard LINQ to SQL query expression:

var query = from c in db.Customers             where c.City == "Nantes"             select new { c.City, c.CompanyName };


As you may know, the variable query returned by the LINQ expression is of the IQueryable type. Here is the definition of the IQueryable type:

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

As you can see, IQueryable contains an attribute of Expression type, and Expression is the base class of Expression <T>. An IQueryable instance is designed to have a related Expression Tree. It is a data structure equivalent to the executable code in a query expression.

Why do I need to convert a query expression from LINQ to SQL into an Expression Tree?

Now we know that the expression tree is a data structure that represents executable code. So why do we need to convert a query expression from a LINQ to SQL statement to an Expression Tree?

A linq to SQL query is not executed in the C # program, but is converted into an SQL statement, sent over the network, and finally executed on the database server. That is to say, the following LINQ query is not executed in the C # program.

var query = from c in db.Customers            where c.City == "Nantes"            select new { c.City, c.CompanyName };

It runs on the database server after being converted to an SQL statement. The converted SQL statement is as follows.

SELECT [t0].[City], [t0].[CompanyName]FROM [dbo].[Customers] AS [t0] WHERE [t0].[City] = @p0

Now you may be able to answer the above questions. You can sum up in one sentence:The Expression Tree is used to convert a query expression to a string (an SQL statement here) and hand it over to other programs (a database server here) for execution.

IQueryable <T> and IEnumerable <T>

As we know, LINQ to Objects usually returns IEnumerable <T>, while LINQ to SQL returns IQueryable <T>. Why do they return different types?

Let's first look at their definitions. Maybe we can find the answer to the question from their definitions.

IEnumberable <T> is defined as follows:

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

IQueryable <T> is defined as follows:

Public interface IQueryable: IEnumerable {Type ElementType {get;} Expression {get;} // Expression Tree IQueryProvider {get ;}}

It can be seen that IQueryable <T> contains the definition of an Expression tree, but IEnumberable <T> does not. This also reveals a phenomenon in which the Expression tree is usually used in LINQ to SQL queries, however, it is rarely used in LINQ to Objects.

So why does the Expression Tree rarely be used in LINQ to Objects? The reason is that the query by using LINQ to Objects can be completed in. net programs, and it does not need to be converted into a string (or an SQL statement) and sent to other programs for execution.

So how can we choose the two return types? There are two principles for reference:

  • If the query expression can be executed in this program, you can use Enumberable <T> to complete the task.
  • If the query expression needs to be converted to a string and sent to other programs for execution, IQueryable <T> and expression tree should be used.
Summary

Through the above learning, we found that the expression tree is not as hard to understand as we can imagine. I want to summarize the expression tree in a few simple words.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.