- 1.1linq execution expression
Before reading this article, I assume that you have some theoretical knowledge of my previous analysis, because the content of this chapter is based on a series of previous knowledge points, to ensure your reading is successful, we recommend that you read the first few articles in your own series of LINQ or you have a deep knowledge system on the principles of LINQ to prevent your valuable time from being delayed.
So far, we have been very clear about the implementation principle of LINQ. From its preliminary conception to its true use, there is sufficient evidence, however, it seems that the problem is not as simple as we think. Problems are always frequently used in our use, especially the use of new technologies. Of course, problems can be improved. [Wang qingpei has all rights reserved. For more information, please sign it.]
I. LINQ execution expression
In the process of studying LINQ, I have referenced many technical articles and technical books. There is no doubt that the call portal of LINQ to provider resolves lambda expressions into expression <t> Expression objects, unlike LINQ to object, LINQ to object directly parses Lambda into a generic func type delegate, but many of us, including myself, have ignored a large detail, that is, the provider will execute expression <t> in the internal part, instead of completely parsing the expression <t> object into an equivalent SQL statement as we understand it, that is to say, expression <t> is not as simple as we can see. It has a dual context logic in it.
We all directly use LINQ as the query interface. At the end of the compilation, VS is responsible for parsing the LINQ syntax and translating it into corresponding extension method calls. We ignore an important link, that is, when vs performs resolution translation on LINQ, it will execute the LINQ expression, which is very important. Previously, I thought that vs was only responsible for translating the LINQ expression into an equivalent extension method call. Later I found that vs concatenates where statements to meet the conditions that we cannot determine the object conditions in the early stage, this function allows us to include a logical judgment expression when writing a LINQ statement. It is very convenient for us to perform multi-condition combination query. We do not need to perform multiple judgments on if and Else, you only need to let it go in the first expression in LINQ to make a decision. Comrades pursuing elegant Code do not want to use two query methods in a method with both LINQ queries and chained queries. If LINQ can satisfy most of the query functions, it would be perfect; [Wang qingpei has all rights reserved. For more information, please sign it.]
To demonstrate that the compiling process of LINQ will be executed by Vs, we can use the linqpad tool to check it;
LINQ query expression: from truck in tb_cx_trucks where 1 = 1 select Truck
Equivalent Link Method of LINQ: tb_cx_trucks.where (truck => true)
Figure 1:
If the execution is not performed, it is resolved directly to the lambda format (truck) => 1 = 1, and then the LINQ to provider is responsible for processing, maybe it doesn't actually mean that it is a constant expression, so it is parsed like this. Let's look at it in another way. [Wang qingpei has all rights reserved. Please give a signature for reprinting]
LINQ query expression: from truck in tb_cx_trucks Where string. isnullorempty ("1111") Select Truck
The equivalent method of LINQ: tb_cx_trucks.where (truck => string. isnullorempty ("1111 "))
Figure 2:
From this, we can draw a conclusion that the LINQ statement will be executed and parsed. When the program is not yet provided, we can see that some execution logic can be attached to the LINQ statement, instead of the final SQL Execution logic.
Expression processing can be divided into constant expressions and dynamic variable expressions. When a constant expression is compiled by Vs, it can directly calculate whether the expression is true or false. Dynamic variable expressions need to be calculated during later expression parsing. In other words, the provider in LINQ to provider is an expression executor with a high IQ, it is not only an equivalent expression parsing, but also contains custom logic code for expression parsing. [Wang qingpei has all rights reserved. For more information, please sign it.]
For example, we have all experienced splicing query conditions. There are n query condition fields on the interface. We need to dynamically splice the fields that the user has entered into the LINQ statement. Generally, we will make the if judgment, because we all think that the conditional expression after where is directly parsed into the corresponding logic SQL statement, therefore, as long as it is spliced, It is parsed into the SQL WHERE clause. Because LINQ cannot be split and assembled, compilation can only be performed once written. Therefore, we are all using the query Extension Method for Data Query. This dilemma makes it impossible for us to see the elegance of LINQ, but it has never been used.
By observing the SQL statement parsed by the linqpad tool, it is found that the LINQ query expression will be executed and parsed within the provider. The process is the same as that of Vs and can be executed first, then, the parsing is based on the previous execution. Let's take a look at a relatively simple SQL and chained method after the resolution of LINQ; [Wang qingpei is copyrighted, please give a signature for reprinting]
LINQ query expression: from truck in tb_cx_trucks where 1 = 1 | truck. license_number.length <10 select Truck
Equivalent link-up method of LINQ: tb_cx_trucks.where (truck => (true | (truck. license_number.length <10 )))
Figure 3:
Compared with the chain method, it is obvious that vs first executes the 1 = 1 expression and returns true as a part of the subsequent expression and concatenates it into the where chain method. Therefore, it first executes and then parses the two processes. Then we analyzed the final SQL statement and did not see any where statement. Why? It is because the provider executes the expressions internally and analyzes the output results we want, and does not know whether this effect is to meet our multi-condition stitching problem.
Since lambda expressions in the where method are not executed if they are executed (truck. LICENSE-NUMBER.Length <10), this provides an interface for our multi-condition concatenation. [Wang qingpei has all rights reserved. For more information, please sign it.]
Let's take a look at the multi-condition combination query example:
After passing the query object on the interface to the data access layer:
View code
1 public List<Truck> GetList(Truck truckModel) 2 { 3 using (KJtest0817Entities DbContext = new KJtest0817Entities()) 4 { 5 var resultList = from truck in DbContext.TB_CX_TRUCK 6 where string.IsNullOrEmpty(truckModel.ENGINE_NUMBER) || truck.ENGINE_NUMBER == truckModel.ENGINE_NUMBER 7 where string.IsNullOrEmpty(truckModel.LICENSE_NUMBER) || truck.ENGINE_NUMBER == truckModel.LICENSE_NUMBER 8 select new Truck() 9 { 10 BRAND = truck.BRAND 11 }; 12 return resultList.ToList(); 13 } 14 }
Such a query of LINQ is indeed very elegant, and it is much easier to judge than the previous ifelse.
View code
1 iqueryable <tb_cx_truck> querylist = dbcontext. tb_cx_truck.asqueryable (); // Initialize an iqueryable object 2 if (! String. isnullorempty (truckmodel. license_number) 3 querylist = querylist. Where (truck => truck. license_number.contains (truckmodel. license_number); 4 If (! String. isnullorempty (truckmodel. truck_model_code) 5 querylist = querylist. Where (truck => truck. truck_model_code.contains (truckmodel. truck_model_code ));
If there are many query conditions, we will write a lot of such judgment code, which is inconvenient and not beautiful. [Wang qingpei has all rights reserved. For more information, please sign it.]
(Note: view the larger image)
Or query between multiple conditions
Although we use the where keyword in LINQ to concatenate query conditions in many cases, there is a requirement that the relationship between multiple conditions is or. As long as the where condition in the SQL statement written by using the LINQ or chained method is followed by the and relationship, we can only use the chained Method for splitting.
View code
1 public List<DutyModel> GetList(DutyModel dutyModel) 2 { 3 using (UserOrgDemo2Entities Context = new UserOrgDemo2Entities()) 4 { 5 IQueryable<TB_DUTY> result = Context.TB_DUTY.AsQueryable(); 6 System.Linq.Expressions.Expression<Func<TB_DUTY, bool>> expressionDUTY = DynamicLinqExpressions.True<TB_DUTY>(); 7 8 if (!(dutyModel.RANK_NO == 0)) 9 expressionDUTY.Or(duty => duty.RANK_NO == dutyModel.RANK_NO); 10 if (!string.IsNullOrEmpty(dutyModel.USER_PRIV)) 11 expressionDUTY.Or(duty => duty.USER_PRIV == dutyModel.USER_PRIV); 12 13 return result.Where(expressionDUTY).Select(tb_duty=>new DutyModel(){ USER_PRIV=tb_duty.USER_PRIV}).ToList(); 14 } 15 }
The key here is foreigners (it is estimated that they are more powerful predecessors. Thank you !) Write a *. CS file, which is an extension method of expression <t> Expression file. It is mainly used for Combined Query between multiple conditions or and.
All said that if the multi-condition combination query is in the and relationship, you can directly use LINQ. If it is or together with and, you can use the above chained query method.
Summary: Actually, there is only one purpose. The parsing process of LINQ is not only a process of "translating programs into SQL", but a process of two stages and four processes, there are many writing methods of LINQ, And the principle should be similar. As long as we take these processing processes into account during Writing of LINQ, it should be very helpful for us to deal with complicated queries. [Wang qingpei has all rights reserved. For more information, please sign it.]