. NET in-depth parsing of the LINQ framework (iv: IQueryable, Iqueryprovider interface Detailed)

Source: Internet
Author: User

Read the catalogue:

    • 1. Introduction
    • 2. Extended LINQ to Object (Application framework with query capability)
      • 2.1. Extending methods by adding ienumerable<t> objects
      • 2.2. By inheriting the Ienumerable<t> interface
      • 2.3. Detailed object Structure diagram
    • 3. Implement iqueryable<t>, Iqueryprovider interface
      • 3.1. Delay loading of Ienumertor<t> objects (improve system performance)
      • 3.2. The secret of extending the extension object of the method (this iqueryable<tsource> source)
      • 3.3. Sub-Methods in the execution of iqueryable<t> (extension methods in queryable)
      • 3.4. Wrong design of chain Query method (Focus: Multiple processing of one execution program)
      • 3.5. Loop execution object model, fragmented execution model (false recursive invocation)
      • 3.6.N Layer Object Execution Model (horizontal-to-vertical vs. chain extension method)
      • 3.7.LINQ query expressions and chained query methods are actually empty shells.
      • 3.8. Detailed object structure diagram (how the object is executed)
      • 3.9.iqueryable<t> and Iqueryprovider one-to-one relationship can be changed into a one-to-many relationship
    • 4. Full Custom Query
1 ". Introduction

Allow me to interrupt your interest before you start reading this article. In fact, this article was originally not intended to add the "Introduction" of this section, and then think it is necessary to feedback the reader's comments. After a detailed explanation of the first three articles, we basically have a basic understanding of the structure of the LINQ framework, including its design model, the model of the object, and know that LINQ query expression is actually the syntax sugar above C #, but this sugar is really good, very convenient very timely, and a series of LINQ supporting principles of the introduction of a large tracts of theory, do not know how the effect;

At the end of the previous article, I saw a senior comment that suggested that I write more about LINQ use than the theory. By the way, I feel that the use of LINQ articles online, there is no need for more than the value of writing, the online LINQ use of articles from the introduction to the complex application is too much, no matter what level of programmers can find the applicable article. I think these articles belong to the use of the class, in the actual project use of the time a little check can be used up on the line, and it is important to understand its principle is our long-term pursuit, because these principles in any application framework design are interlinked, can help us extrapolate learning, reduce learning costs, Constantly improve the internal design ideas.

The so-called design ability embodies the technical level, this sentence is not false. Comrades, we are constantly pursuing the design, not the use of it. When you understand the principle, I think everyone can think out a variety of application direction, then the development of technology is meaningful, of course, this is the most valuable.

2 ". Extend LINQ to Object (application framework has query capabilities)

We know that the query scope supported by LINQ is mainly in Ienumerable<t>, iqueryable<t>, and the query capabilities we want to extend LINQ are mainly in these two pieces. Many times when we write the application framework, we will implement the Ienumerble<t> object ourselves, generally do not use the system-provided collection classes, so that the framework of OO, contextual coherence, more modeling. If the application framework has a certain query ability is not very convenient. For example, you are developing a data-intensive framework that may not be persisted in real time, but can provide some sort of query tool to query the data in memory externally, so this time we need to extend the object query capability of LINQ. In this section we will learn how to extend LINQ to Object.

The LINQ query object is based on the Ienumerable<t> object, not what the collection object has to look for. A LINQ query for a Ienumerable<t> object is a enumerable static object that is supported and then represented by an anonymous expression, which allows for a natural query collection. So how do we do this? Extend LINQ to Object? In fact, two points can be extended, or provide an extension method to extend the Ienumerable<t> object, of course, you do not attempt to let vs support some kind of keyword to allow you to correspond to the extension method. There is also the inherited Ienumerable<t> object that allows our own collection types to have a strong type of LINQ query capability. Of course, depending on our needs, from a technical point of view, only these two points can be expanded.

If we use extension methods then we can only extend the Ienumerable<t> object, which is fine. We can easily call our own extension methods in LINQ expressions, and let our methods follow a chained query. If we inherit from the Ienumerable<t> object extension, then the situation will be a little complicated, your extension method to extend the object must be specific to the definition of the object, if you extend the object can not and inherit the object persisted, then you will be disconnected all extension methods.

2.1 ". Extending methods by adding ienumerable<t> objects

Let's take a look at the above theory through concrete examples, and see how to extend the system's Ienumerable<t> object by extending the method.

Code Snippet: Order class

View Code

This is an order class purely for demonstration purposes, with three attributes "Ordername (order name)", "Ordertime", "Ordercode (order number)", followed by these three properties to match the completion of the example.

If we are directly using the Ienumerable<t> object provided by the system, we only need to build the extension method of the Ienumerable<t> object to implement the extension of the collection type. I assume that list<t> is used to hold the information for a batch of orders, but according to the business logic we need to support the processing of the order collection data by providing a set of independent extension methods. This set of independent extension methods will follow the current system deployment, not as part of a common development framework. This is convenient and flexible, and can replace some of the service layers in the layered architecture, the logic snippet of the BLL layer, and look more elegant.

Again, we can even do a lot of articles in the extension method, the extension method into the system architecture analysis, the use of extended approach to encapsulate streamlined processing logic, the fragmented processing of business, verification of chain processing is very good. Only in this way can we really let this technology take root, in order to use it flexibly in the actual system development.

Let's build a simple ienumerable<t> extension method that handles whether data in the current collection can be inserted into the data.

Code Snippet: Ordercollectionextent Static class

View Code

Ordercollectionextent is a simple extension method class that has only one whereorderlistadd method, which is to determine whether the order object in the current collection satisfies the insert condition, the condition is not the focus, only satisfies the needs of the example. This method needs to be preceded by the order type generic constraint, so that the extension method is not used by other types.

View Code

If. NET supports extended Properties "but Microsoft is sure to support attribute extensions in the late stages, and it doesn't use methods to make similar judgments." So do we gracefully perform the logic of the previous BLL layer processing, and this part of the extension method can be changed dynamically, can be built in a separate assembly. By the way, in the current MVVM pattern, many of the interface logic in V can be encapsulated in extension methods to reduce the coupling and complexity in the VM by using the idea of extension points. Including today's MVC, the extension method can be used appropriately to achieve a more convenient usage pattern.

But in most cases we are expanding on all types of ienunerale<t>, which can be a good combination of LINQ's chained programming. The principle is so much, according to the specific project needs appropriate adoption.

2.2 ". By inheriting the Ienumerable<t> interface

I think most of the time we are directly using the Ienumerable<t> implementation class, but in writing system components, the framework is usually to implement their own iterator class. Then the extension method at this time can also be applied to the class we inherited, which is quite handy, and unknowingly our own extended component will also support LINQ queries. But this time should be appropriate to control your extension to the inherited classes, extension methods should be for your internal use, can not be contaminated to external objects.

We continue to look at the example, which is for the inheritance ienumerable<t> to analyze the use mode;

View Code

This is the Order collection type Ordercollection class, which is designed to hold or process the Order class. Whether it is from compatibility. NET2.0 or other considerations may encapsulate the type of the collection in the. NET2.0 version of the assembly, the version above. NET2.0 will provide an extended version of the assembly, this time our extension method is specifically for the ordercollection to write, otherwise it will cause Pollution of ienumerable<t> objects.

View Code

This time will be very clean use of their own extension method, will not cause a large area of pollution. Of course, the dependency inversion principle will have high-level abstraction, do not directly extend the implementation of the class, here is just a simple introduction.

2.3 ". Detailed object Structure diagram

This summary mainly ienumerable<t> and its extension methods including LINQ query for a complete structural analysis, will give detailed object structure map.

Object static model, run-time map:

The key part of this is that i==10 will be encapsulated into an expression directly into the Where method, and I, after Select, is also the expression "(int i) =>i", which will also be fed into the Select method, which is not drawn here. Understanding,ienumerable<t> is the data source for LINQ to Object, and the enumerable static class is specifically designed to extend the Query method in a LINQ query expression, so when we write a LINQ query IEnumerable <T> collection is, in fact, in the indirect invocation of these extension methods, but we do not need so tedious to write lambda expression, by the editor to help us dynamically generated.

Summary: This section mainly explains the principle of LINQ to Object, in fact, the main principle is that lambda expression into the enumerable extension method, and then form a chain operation. Linq is just a language that assists us in fast querying, not. NET or a part of C #, in any. Can be used in languages on the net platform. Below we will focus on LINQ to Provider so that we can really make advanced applications for LINQ.

3. ". Implement Iqueryable<t>, Iqueryprovider interface

The focus of this article is to explain the iqueryable<t>, iqueryprovider two interfaces, when we understand the two interfaces, we can use the imagination to implement any data source query. Iqueryable<t>, Iqueryprovider Two interface or there are a lot of good things worth our research, which is flooded with a lot of design patterns, data structure of knowledge, we will slowly analyze its beauty.

The Iqueryable<t> interface is the entry point for LINQ to Provider, and it is interesting that it is not a iqueryable<t> to support a query. When we write LINQ statements, we are generally where and then select what, at least two successive extension method mappings call, but friends do you know how it is handled internally? Whenever the where is followed by select how do they correlate a complete query? Iqueryable<t> is not a ienumerable<t> object, it cannot be processed in real time and then returns the result to the next method for execution. So how does it string the fragment execution method into an integer, complete query? Below we will analyze the model, data structure, framework principle, which understand the code is the performance of the model, and let its natural understanding.

3.1 ". Lazy loading of ienumertor<t> objects (improves system performance)

Lazy-loading techniques are already in use before LINQ, but few people pay attention to it and are hidden behind the system's framework. In many cases, we need to build our own capabilities for lazy loading, and building a delay in a Ienumerable<t> object basically builds a state machine through yield return, and returns the data when the iteration is performed. In iqueryable<t>, the data is obtained by executing the provider program to reduce the performance cost of obtaining data at the outset. Iqueryable<t> inherits from the Ienumerable<t> interface, which can be called by the foreach syntax, but does not execute the provider's code in the GetEnumerator method. Let's examine the code for the Iqueryable<t> interface.

View Code

This is the two way to return the IEnumerator interface type from the ienumerable<t> in the Iqueryable<t> interface, in the LINQ to SQL that we are currently using, LINQ to Entity will return a strongly typed collection object, generally do not do real-time data query operations, if you want to perform real-time execution needs to be iqueryable<t> The direct invocation of the Provider.execute method.

We use graphs to analyze the principle of lazy loading in LINQ to provider;

This code will not be executed immediately, and we'll track the execution of each component.

This graph focuses on the continuous operation of the Iqueryable<t> object, and the approximate principle is that each time the extension method is executed, a new iqueryable<t> will be constructed, and the iqueryable<t> The object will contain the expression tree that was last executed, and so on, forming a large expression tree. The detailed principle is analyzed in the following subsections.

The final orderlist will be an object of type iqueryable<t> that contains the complete expression tree, and this time if we do not make any use of the query will not trigger the data. This is the key to lazy loading. If you want to get data from orderlist immediately, you can perform orderlist manually. Provider.execute<tb_order> (orderlist. Expression) to get the data.

3.2 ". The secret of extending the extension object of the method (this iqueryable<tsource> source)

In fact, there is a thinking trap, when we analyze the source only focus on the extension method in the following parameters, rather than focus on the extension method to expand the object itself, seemingly different methods in different places, actually they come from a place, where the logical object is a, But this is exactly what will cause us to analyze the problem bottleneck, here we focus on the extension method to expand the object.

We use the source code directly to explain it;

View Code

This is the source code for the Select extension method in the Queryable class, which extends the Iqueryable<tsource> object, inside the method using the source object, and source is a direct reference to the extension object. This is the point of the problem, and it is difficult for a friend who is unfamiliar with extension methods or chained programming to concatenate the source into the Iqueryable<t> object returned by the previous method. According to the code analysis here, source each time represents the iqueryable<t> instance, regardless of which time you make the call to the method, it represents the object you are currently calling the method, so no matter how many times we make the call they are coherent, Just like a doubly linked list in a data structure, after this method is processed, the next method will be the method of this object. So be aware that this call is going to be the last call, not the beginning of a new one. Understanding this is critical to the subsequent LINQ analysis.

3.3 ". Sub-Methods in execution iqueryable<t> (extension methods in queryable)

all know that LINQ query is a number of keywords splicing together, row into a continuous query semantics, which behind the principle of the article up and down also said many times, I think should also be roughly understood. In fact, this is a bit like the big problem broken down into a number of small problems to solve, but not all in order to decompose the problem and so design, in the chain query many keywords in different query context are common, such as where can be used in the query, can also be used in the update, delete. The issues discussed here may already be more than LINQ, but they make sense because they have similar design models.

According to the meaning in the 3.2 diagram, we already know that the objects that are transferred between extension methods are from different instances but from an object type, so why do you want to perform each keyword operation in segments? Let's use the diagram to help us analyze the problem.

Both lines of code refer to the Where method, and all require stitching conditions, but the conditions created by the Where method do not affect your previous methods. The benefits of segmented execution are here, where maximum granularity of decoupling can be reused for the most part.

3.4 ". Error in design of chain Query method (emphasis: Multiple processing of one execution program)

When using iqueryable<t>, we try to analyze the source code, see IQueryable Internal use principle to help us generate expression tree data, we let it naturally see the Provider property, which is the Iqueryprovider interface, According to the note, we understand that it is the last provider to execute the query, and we take it for granted that the starting instance of Iqueryable<t> is the portal to the query, and that it maintains a unique instance of the extended method of successive calls, and finally it gets all the expressions in its entirety. form an expression tree. But iqueryable<t> with us a joke, its call to the final return do not know how much to do createquery. Seemingly once execution but hide multiple method calls, the background secretly built we do not know the execution model, let people ecstatic. Let's uncover how the iqueryable<t> is handled in a chained way, and see how deep it's hidden.

View Code

Similar to this code in the article has appeared on the above, very similar, we have a detailed analysis of its internal principle, in the end is how to build a dynamic but static object model.

This method has a parameter, is a conditional expression, and this method extends the Iqueryable<t> interface, any derivation can be used directly. The return type of the method is also the iqueryable<t> type, and the return type and extension type are the smallest loops that already form the chained programming. There are two judgments in the method, the first of which is to determine whether the code is invoked by means of an extension method, to prevent us from using the extension method directly, and the second is to decide if we are providing an expression.

So the point is the last line of code, which wraps several layers of method calls, what exactly does it mean? When we decompose in detail, it dawned on us naturally.

Because of the complexity of the problem, there is no comprehensive iqueryable<t> context analysis to guarantee the integrity of this section. Through, we can probably analyze the Iqueryable<t> object is the invocation of each method will produce a new instance, the instance is then naturally accepted by the next method, called in turn.

interface-oriented design pursues separation of duties, why do we put execution and creation iqueryable<t> in iqueryprovider<t>? If the creation of the iqueryable<t> extraction process to form a separate creation interface I feel more ingenious, of course, this is just my guess, perhaps the understanding is wrong.

. NET in-depth parsing of the LINQ framework (iv: IQueryable, Iqueryprovider interface Detailed)

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.