Linq Coding-- Part Nine(IEnumerable、IQueryable、Set)

      Enumerable 是 .NET FX 3.5 System.Linq 中新增的类型,实现了大量 IEnumerable<T> 扩展方法, 所有直接或间接实现该接口的类型都可以使用 Linq to Object 语法; 而 Queryable 则针对 IQueryable<T> 扩展,主要用于 DLinq 的操作,IQueryable<T> 继承自 IEnumerable<T>。

提供对未指定数据类型的特定数据源的查询进行计算的功能。 IQueryable 接口由查询提供程序实现。 该接口只能由同时实现 IQueryable<(Of <(T>)>) 的提供程序实现。 如果该提供程序不实现 IQueryable<(Of <(T>)>),则无法对提供程序数据源使用标准查询运算符。 IQueryable 接口继承 IEnumerable 接口,以便在前者表示一个查询时可以枚举该查询的结果。 枚举强制执行与 IQueryable 对象关联的表达式目录树。 “执行表达式目录树”的定义是查询提供程序所特有的。

例如,它可能涉及将表达式目录树转换为适用于基础数据源的查询语言。

在调用 Execute 方法时将执行不返回可枚举结果的查询。

IEnumerable和IQueryable的区别:

    In one of our current projects we're using LINQ TO SQL to conquer the object-relational impedance mismatch. We all had some experience with LINQ and deferred execution. But it was getting obvious that we all needed to deeply internalize the difference between IEnumerable and IQueryable. 
    EntitySet<T> and Table<T> both implement the IEnumerable<T> interface. However, if there would not be IQueryable all querying functionality - including filtering and sorting - would be executed on the client. To optimize a query for a specific data source we need a way to analyze a query and its definition. That’s where expression trees are coming in. As we know an expression tree represents the logical definition of a method call which can be manipulated and transformed. 
    So we have a mutable logical definition of our query on one side and a queryable data source on the other. The Property Provider on IQueryable now returns an IQueryProvider which is exactly what we need here. 

Code
public interface IQueryProvider { 
  IQueryable CreateQuery(Expression expression); 
  IQueryable
<TElement> CreateQuery<TElement>(Expression expression); 
  
object Execute(Expression expression); 
  TResult Execute
<TResult>(Expression expression); 


      There are 2 interesting operations and their generic counterparts. The generic versions are used most of the time and they perform better because we can avoid using reflection for object instantiation. CreateQuery() does precisely what we are looking for. It takes an expression tree as argument and returns another IQueryable based on the logical definition of the tree. When the returned IQueryable is enumerated it will invoke the query provider which will then process this specific query expression. 
    The Execute() method now is used to actually executing your query expression. This explicit entry point – instead of just relying on IEnumerator.GetEnumerator() – allows executing ET’s which do not necessarily yield sequences of elements. (For example aggregate functions like count or sum.) 
    We finally have our two worlds nicely connected together. The mutability of ET and the deferred execution of IEnumerable combined to a construct that can analyze an arbitrary mutated and extended query at the last possible moment and execute an optimized query against its data source. It’s not even too hard to implement your own IQueryProvider for your own data source. Maybe I’ll cover that in a later post. This is really nice work Eric Meijer and his team has done here.

 

     明白了以两者的区别和概念之后,下面再来以直观的代码方式看看有关于LINQ Set操作几个扩展方法 

 1   List < Int32 >  numbers  =   new  List < Int32 >  {  21 265 236 21 956 456 456 535 236  };
 2 
 3   List < Int32 >  numbersTwo  =   new  List < Int32 >  {  21 456 535 236  };
 4 
 5           ///   <summary>
 6           ///  列出回序列中的非重复元素。        
 7            ///   </summary>
 8           public   void  Distinct()
 9          {
10              IEnumerable < Int32 >  distinctNumbers  =  numbers.Distinct();
11 
12               // IQueryable<Int32> distinctNumbers = numbers.AsQueryable().Distinct();
13   
14              Console.WriteLine( " Distinct numbers: " );
15   
16               foreach  (Int32 number  in  distinctNumbers)
17              {
18                  Console.WriteLine(number);
19              }
20          }
21 
22           ///   <summary>
23           ///  列出的序列只显示在第一个序列中的元素。
24            ///   </summary>
25           public   void  Except()
26          {
27              IEnumerable < Int32 >  exceptNumbers  =  numbers.Except(numbersTwo);
28 
29               // IQueryable<Int32> execeptNumbers = numbersTwo.AsQueryable().Except(numbers);
30   
31              Console.WriteLine( " Except numbers: " );
32 
33               foreach  (Int32 number  in  exceptNumbers)
34              {      
35                  Console.WriteLine(number);
36              }
37          }
38 
39           ///   <summary>
40           ///  进行比较生成两个序列的交集。
41            ///   </summary>
42           public   void  Intersect()
43          {
44              IEnumerable < Int32 >  intersectNumbers  =  numbers.Intersect(numbersTwo);
45 
46               // IQueryable<Int32> intersectNumbers = numbersTwo.AsQueryable<Int32>()
47                                                               .Intersect(numbers);
48 
49              Console.WriteLine( " Intersect numbers: " );
50 
51               foreach  (Int32 number  in  intersectNumbers)
52              {
53                  Console.WriteLine(number);
54              }
55          }
56 
57           ///   <summary>
58           ///  执行的联合操作。返回的序列包含两个输入序列的唯一的元素。
59            ///   </summary>
60           public   void  Union()
61          {
62              IEnumerable < Int32 >  unionNumbers  =  numbers.Union(numbersTwo);
63 
64               // IQueryable<Int32> unionNumbers = numbersTwo.AsQueryable().Union(numbers);
65   
66              Console.WriteLine( " Union numbers: " );
67   
68               foreach  (Int32 number  in  unionNumbers)
69              {
70                  Console.WriteLine(number);
71              }
72          }
73   
74           ///   <summary>
75           ///  连接两个序列。
76            ///   </summary>
77           public   void  Concat()
78          {
79              IEnumerable < Int32 >  concatNumbers  =  numbers.Concat(numbersTwo);
80 
81               // IQueryable<Int32> concatNumbers = numbersTwo.AsQueryable().Concat(numbers);
82   
83              Console.WriteLine( " Concat numbers: " );
84 
85               foreach  (Int32 number  in  concatNumbers)
86              {
87                  Console.WriteLine(number);
88              }
89          }

 

LINQ Coding 目录

More Linq Coding

你可能感兴趣的:(Linq Coding-- Part Nine(IEnumerable、IQueryable、Set))