IQueryable and Iqueryprovider in the C # Entity framework

Source: Internet
Author: User
Tags reflector


Objective

I believe you are right

Entity Framework

Certainly not unfamiliar, I believe that LINQ to SQL is one of its biggest bright spots, but we have been using until now do not understand how the internal implementation, today we will briefly introduce IQueryable and Iqueryprovider.


IQueryable interface

Let's talk about this interface first, because we often see the return type of a LINQ to SQL statement in the use of EF

IQueryable

, we can look at the structure of this interface:


The code is as follows:


public interface Iqueryable:ienumerable

{

Type ElementType {get;}

Expression expression {get;}

Iqueryprovider Provider {get;}

}

It may be strange to say that when we use this interface in the development process, we provide more than that, because Microsoft provides a powerful

Queryable

Class, of course, you do not think that this class is implemented IQueryable and then implement a lot of methods, if so those third-party library How to customize it? So queryable is just a static class, the IQueryable interface is extended, the following is the author in


. Net Reflector


Part of:

If the reader is careful, you will find that LINQ to SQL does not lead to actual queries, and only start querying data from the database when we actually start using it.


Iqueryprovider interface

If we debug the EF, we'll see the generated T-SQL statement. T-SQL is based on the expression tree analysis, and the core is the Iqueryprovider interface, the following is the structure of the interface:


The code is as follows:


public interface Iqueryprovider

{

IQueryable createquery (expression expression);

Iqueryable<telement> createquery<telement> (expression expression);

Object Execute (expression expression);

TResult execute<tresult> (expression expression);

}

which

CreateQuery

is responsible for parsing the expression tree, of course, but also to return the results of processing, in order to continue to analyze the following statement, of course, this is only analysis, you can completely according to the expression tree to get your own query statements, such as SQL or other, only when the actual use of data will be called

Execute

method, this time we can start the actual query according to our own analysis of the statement.


Example analysis


Queryprovider class

We can never understand the principles, so let's take a simple example to illustrate the following. First we implement the Iqueryprovider interface, which will use a query class, this class will be introduced later, first we create a new

Queryprovider

class implements the Iqueryprovider interface, first we look at the

Createquery<s>

Method:

Here's

Expression

Is the expression tree that is passed to us and needs to be processed, and finally we return an example of implementing the Iqueryable<s> interface so that LINQ can make the following query on this basis, where we just create an instance of query, Pass expression to it at the same time, because here is just a demo, so we don't really parse the expression tree

(That's a lot of work to do)

。 Then there is the CreateQuery method:

We can see the following phrase:

The actual meaning is to create

Query<>

, and the generic parameter is

ElementType

, the parameter is

This

And

Expression

The Last is

Execute

method, passing a

Expression

Parameters, and get the final result, the author here directly is the value of the Write dead:


Query class

Only

Queryprovider

No, we also need a class that can save the state of the expression tree, and of course the result of our parsing of the expression can be saved in it, so that we can execute the execution and return the result in the Iqueryprovider Execute method based on the results we parse.

Here we can see the expression value of query when creating this instance, if the expression parameter is not passed when the value is:

However, in the following procedure, expression in query will be the expression value in Queryprovider.

In fact, we have completed a simple example, we can begin to test our results, the author is using the following code to test:

OK, let's start by looking at how this LINQ statement is analyzed.

First we look at the return value of expression in query at the beginning of the execution (for example):

After getting to this expression, we begin to execute LINQ, where item = = 123 is executed first.


Analyze where item = = 123

Then we F5, we can see the queryprovider in the

Createquery<s>

Hit, and

Expression

The parameters are as follows:

We see that the string inside is


Where (item = = 123)


In this sentence we can understand that in fact, where in LINQ is essentially the use of the Where method, and pass it to its corresponding lambda expression. After analyzing the where section, here is

FirstOrDefault

Part of it.


Analysis FirstOrDefault

When executed to

FirstOrDefault

When we can look at the value of T, we find that T is actually the return value of createquery<s> in Queryprovider.

And then we start doing the following

FirstOrDefault

method, the discovery will once again get

Expression

, and the value of expression at this point is the top

Createquery<t>

The arguments passed to us

Expression

This expression tree is then represented by an expression tree

FirstOrDefault

The values of the method call are spliced together and the Execute<s> method in Queryprovider is called, and we can see the value of the expression passed to us at this time.

At this point a simple process is over, and the end is to return the author to write dead 123 of this value.

Through the above example we have a basic understanding of the process of its work, below we will be a step-by-step analysis of our

where item = = 123

, of course, we will use recursion, so please tidy up your own ideas, step by step to see how to parse this statement from an expression tree.


Parse an expression tree in combat

First, we have a method of analyzing the expression tree, which we put in

Queryprovider

In


The code is as follows:


public void Analysisexpression (Expression exp)

{

Switch (exp. NodeType)

{

Case Expressiontype.call:

{

Methodcallexpression MCE = exp as methodcallexpression;

Console.WriteLine ("The Method is {0}", MCE.) Method.name);

for (int i = 0; i < MCE. Arguments.count; i++)

{

Analysisexpression (MCE). Arguments[i]);

}

}

Break

Case Expressiontype.quote:

{

Unaryexpression UE = exp as unaryexpression;

Analysisexpression (UE. Operand);

}

Break

Case EXPRESSIONTYPE.LAMBDA:

{

LambdaExpression le = exp as lambdaexpression;

Analysisexpression (le. Body);

}

Break

Case Expressiontype.equal:

{

Binaryexpression be = exp as binaryexpression;

Console.WriteLine ("The Method is {0}", exp. Nodetype.tostring ());

Analysisexpression (BE. left);

Analysisexpression (BE. right);

}

Break

Case Expressiontype.constant:

{

ConstantExpression CE = exp as constantexpression;

Console.WriteLine ("The Value Type is {0}", CE. Value.tostring ());

}

Break

Case Expressiontype.parameter:

{

ParameterExpression PE = exp as parameterexpression;

Console.WriteLine ("The Parameter is {0}", PE. Name);

}

Break

Default

{

Console.Write ("Unknow");

}

Break

}

}

And in


Createquery<s>


Call this method in the

Then we can start to run the test, in order to let the reader understand the current processing of the expression tree, so in the following will contain


Analysisexpression in Parameters Exp


, which makes it easy for the reader to distinguish between the currently processed expression tree.

The NodeType in the Ps:expression type is very important because the parent expression type is passed to us, and we need to convert the NodeType to the corresponding subclass so that we can get more detailed information.


Expressiontype.call

We enter this branch according to the NodeType of the first exp, because where is essentially the SS call where method, so we convert exp to the corresponding

Methodcallexpression

Type so that we can see the method name of the call.

Of course call a method must have parameters, so the following also need to loop

Arguments

To analyze the specific parameters, including the object that calls this method, naturally we first parse the object that calls this method, here we make the first recursive call, jump to expressiontype.constant.


Expressiontype.constant

NodeType for this type, we can go through

ConstantExpression

Type to get the corresponding parameter, through value we can get to the object that called the Where method, of course, here will not continue to analyze the downward.

So let's go ahead and jump to the previous for loop and start analyzing the second parameter, which is the part of item = = 123.


Expressiontype.quote

If a person who has touched a lambda may think that the type should be a lambda, but actually does not jump directly to that, but first jumps to quote, and then we convert to

Unaryexpression

Type, and then continue to analyze where


Operand


property, and the NodeType of this property is lambda. Personally, this should be a way of distinguishing between lambda and common, because where not only can receive lambda but it can also be a regular method, so this layer is needed.


Expressiontype.lambda

Jump to this, people will not feel strange, here for brevity. The author does not analyze the parameters, but directly analyzes

Body

Part, because this part is the key to us.


Expressiontype.equal

We see this lambda is very simple, is an equal comparison, so jump directly to the equal, and of course, and, or and other corresponding enumeration, and to this step we can directly analyze left and right, of course there is a small episode, When I look at the exp type when I jump to this enumeration, it's actually

Logicalbinaryexpression

Type, not

Binaryexpression

Type, and then use the reflector to view the next, I will hehe.

I was also surprised, how did not have this type, finally knew to play is this out. So far, let's continue to analyze the left and right parameters of this equality operation.

The first analysis is the left parameter item.


Expressiontype.parameter

Item is picked up and converted into

ParameterExpression

Type, the author only outputs the name of the parameter here.

To the left of the parameter analysis is complete, we begin to analyze the right parameters.


Expressiontype.constant

We can easily think of the corresponding value is 123, to this entire expression analysis is complete.

Let's look at the output of the final console.

I would also like to state that we should understand the principles of the various libraries we use, so that we will be able to add some features that match the actual development in the future, which is not a waste of time. But to improve the development of the project in the future, with the continuous accumulation, we will find a lot of repetitive features do not need us to repeat the writing, and the time saved we can do what we want to do, so we have to do a lazy programmer thinking.

In addition to the Declaration, Running GuestArticles are original, reproduced please link to the form of the address of this article
IQueryable and Iqueryprovider in the C # Entity framework

This address: http://www.paobuke.com/develop/c-develop/pbk23160.html






Related content The timing of dynamic add event bindings for controls in C # Seven classic sorting algorithm series (top) A tuple instance of the new C # syntax features how to use regular expressions to judge characters in C #
An example of the use of a singleton pattern in design Patterns in C # programming super cool WPF implementation loading control effects C # Methods for implementing Windows Form copy content to the Clipboard method for drawing rounded rectangles in C #

IQueryable and Iqueryprovider in the C # Entity framework

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.