from:http://blog.csdn.net/ydm19891101/article/details/50969323
Whether in ADO or in other LINQ uses, we often encounter two important static classes enumerable, Queryable, which are under the System.Linq namespace. So how are these two classes defined and what do they do? Especially the Queryable class, what does it have to do with EF's lazy-loading technology?
Well, take the above questions and start our study today.
First, we introduce the definition of two classes.
(1) The enumerable class, which extends the collection that inherits the Ienumerable<t> interface;
(2) The Queryable class, extended for collections that inherit the Iqueryable<t> interface.
Before we go on, let's take a look at the entity sets defined in EF dbset<t>
Through the above we can see that dbset<t> implements the Iqueryable<t>, ienumerable<t> interface.
The combination of the above two sentences means that the dbset<t> can be extended by two static classes. In fact, look at the source code of two classes can be known, these two classes to implement the iqueryable<t>, Ienumerable<t> interface of the collection of a number of ways to expand.
You may not yet know how to define and manipulate extension methods, please refer to another article: understanding of C # extension methods
But the extension method is not all we need, and what we use most in the ADO is the extended where method.
The where extension methods in two classes are defined as follows
(1) Enumerable class
[CSharp]View PlainCopy
- Public static ienumerable<tsource> where<tsource> (thisienumerable<tsource> source, Func <tsource, bool> predicate);
- Public static ienumerable<tsource> where<tsource> (thisienumerable<tsource> source, Func <tsource, int, bool> predicate);
Observing the Where method, you can see that the first parameter is a class that implements the Ienumable interface, and the second parameter is a func<t> delegate type
(2) Queryable class
[CSharp]View PlainCopy
- Public static iqueryable<tsource> where<tsource> (thisiqueryable<tsource> source, Expression<func<tsource, bool>> predicate);
- Public static iqueryable<tsource> where<tsource> (thisiqueryable<tsource> source, Expression<func<tsource, int, bool>> predicate);
Observing the Where method, you can see that the first parameter is a class that implements the Ienumable interface, and the second parameter is a expresssion type
Obviously, the where method of the two-class extension is different, what is the difference? So what does this difference lead to?
OK, continue learning with doubt.
To make it easy for everyone to learn, here we write a piece of code that looks at the difference between the two through a monitoring tool.
First on the code
[CSharp]View PlainCopy
- Private void Form1_Load (object sender, EventArgs e)
- {
- using (democontext context = new Democontext ())
- {
- var customer = Context.cunstomer.Where (c = c.name = = "Peony");
- foreach (var item in customer)
- {
- MessageBox.Show (item. Id.tostring ());
- }
- }
- }
As for context definitions and entity sets in code you don't have to tangle, we're here to see the essence through appearances. Add breakpoints in the program above, and start the SQL Server Profiler monitoring tool to run the program.
The program will stop at the breakpoint, as shown below
Above is just the point breakpoint, of course, the statement at the breakpoint is executed, continue stepping.
The statement where the breakpoint was executed, the monitoring tool, or nothing at all.
Gee, what's the problem? Why is there no query statement execution? Is the surveillance tool really a problem?
Continue single-Step debugging
Hey, this time how to appear SQL query statement. Oddly enough, this is the lazy-loading technique of the ADO, which is a very important part of the implementation of the IQueryable interface (let's put it to the end).
Having talked about the where method of the Queryable class, let's look at the where method of the Enumable class.
Modify the above code as shown below
[CSharp]View PlainCopy
- Private void Form1_Load (object sender, EventArgs e)
- {
- using (democontext context = new Democontext ())
- {
- var customer = Context.cunstomer.Where (c = c.name = = "Peony"). AsEnumerable ();
- foreach (var item in customer)
- {
- MessageBox.Show (item. Id.tostring ());
- }
- }
- }
Also open the Monitoring tool, add breakpoints, run the program
Single-step debugging, continue running
Executes the statement where the breakpoint is located and executes the query statement.
A summary of the two tests above is summarized below.
(1) All the filtering, sorting, and other operations for IEnumerable occur in memory. This means that the data has been fetched into memory from the database and is only filtered and sorted in memory.
(2) All the filtering, sorting, etc. of the IQueryable will only be queried in the database when the data is actually used. This is also where LINQ's lazy loading core lies.
That last question, why is the IQueryable interface so special?
Observe the definition of it
[CSharp]View PlainCopy
- Summary:
- Provides the ability to calculate a query for a specific data source that does not specify a data type.
- Public Interface Iqueryable:ienumerable
- {
- //Abstract:
- //Gets the type of the element returned when executing the expression tree associated with this instance of System.Linq.IQueryable.
- //
- //Return Result:
- //A System.Type that represents the type of the element that is returned when the expression tree associated with it is executed.
- Type ElementType { get;}
- //
- //Abstract:
- //Gets the expression tree associated with the instance of System.Linq.IQueryable.
- //
- //Return Result:
- //System.Linq.Expressions.Expression associated with this instance of System.Linq.IQueryable.
- Expression expression { get;}
- //
- //Abstract:
- //Gets the query provider associated with this data source.
- //
- //Return Result:
- //System.Linq.IQueryProvider associated with this data source.
- Iqueryprovider Provider { get;}
- }
The interface has three special properties, the specific content code has been introduced, then the query is how to execute it exactly?
The answer is that the interface caches the query expression in the expression tree first, and only when the true traversal occurs, will the expression tree be parsed by Iqueryprovider, and the SQL statement executed to perform the database query operation.
Gee, it's almost finished now.
The above describes the two interfaces of the difference and contact, the specific use of which is to see their own project requirements.
Finally, add the List.where () method or the code description.
[CSharp]View PlainCopy
- list<string> fruits =
- New list<string> { "Apple", "Passionfruit", "banana", "Mango" ,
- "Orange", "Blueberry", "Grape", "Strawberry"};
- ienumerable<string> query = fruits. Where (fruit = fruit. Length < 6);
- foreach (string fruit in query)
- {
- Console.WriteLine (fruit);
Look at the definition of list<t>, as shown in
It is also inherited from the IEnumerable interface, so that he does not exist for lazy loading. OK, to this, all the work is done.
Deep understanding of the differences between the IEnumerable and IQueryable two interfaces