LINQ查询基础知识


SQL #linq2012-05-03 09:34

LINQ 语言集成查询(Language INtegrated Query)作为.net平台的一项查询技术,给我们的开发带来了极大地方便。本人用2.0的平台时间较长,对LINQ用的不是太多。LINQ查询的数据源:实现IEnumberable<T>接口的对象、关系数据库、数据集(DataSets)以及xml文档。最近偶使用到它,谈谈一下使用基础与体会。

   LINQ与T-Sql语法类似,有一些数据库基础的理解它应该不难。下面主要从我使用到的几个函数等来进行说明。

  1、Except

  2、Cast

  3.  Take、TakeWhile

  4、Skip、SkipWhile

  5、Lambda表达式基础

  首先,还是从最基本的查询语法说起。由于LINQ查询结果是IEnumerable<T>,接收返回结果时定义为var比较简洁。最基本的查询语法为:from [parameters]  in [dataSource] select [result].示例代码和截图还是最直接:

#代码

 int[] arr1 = new int[] {1, 2, 3, 4, 5};

            int[] arr2 = new int[] {1, 2, 5, };

            var result = from a in arr1

                         join b in arr2 on a equals b into list

                         from r in list

                         select r;

            foreach(var v in result)

            {

                Console.WriteLine(v.ToString());

            }

输出结果如下:

 

以上的查询是将两个集合中相同的元素查出来,放入到list中,然后再从list中进行查询。

在Select中,也可以自定义需要选择的结果。如需要找出两个集合中相同元素的长度,代码如下:

string[] list1 = new string[] {"ab", "bc", "abd", "aaaa"};
            string[] list2 = new string[] { "ab",  "abd", "aabb","bb" };

            var query = from s in list1
                        join m in list2 on s equals m
                        select new {s.Length};
                        foreach( var len in query)
                        {
                            Console.WriteLine(len.Length);
                        }

输出结果如下:

2,3

 

在查询时候用判断元素相等用的是equals,而不是编程语言中的"=="或者T-SQL中的"=",有点特别。

1、Except:返回查询两个集合中差异的元素。

    var dif = arr1.Except(arr2);
            foreach (var item in dif)
            {
                Console.WriteLine(item);
            }

这样dif就包含3,4两个元素

2、Cast:对数据源中元素进行类型转化,转化的目标类型为Cast指定的泛型。

  Console.WriteLine("Cast************");

            object[] obj = new object[] {1,2,3};

            var intResult = obj.Cast<int>();

            foreach( var item in intResult)

            {

                Console.WriteLine("item :{0}",item.GetType().ToString());

                Console.WriteLine(item);

            }

输出如下:

 

3.  Take、TakeWhile:Take(int i)从数据源起始位置返回指定数量的个数。如果指定的参数为-1,则返回为0,若指定的参数大于数据源的个数,则返回全部数据。TakeWhile需要指定委托来实现获取元素.它有两个重载。一个参数的委托MSDN给出的解释如下:

【此方法通过使用延迟执行实现。即时返回值为一个对象,该对象存储执行操作所需的所有信息。只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。

TakeWhile<(Of <(TSource>)>)(IEnumerable<(Of <(TSource>)>), Func<(Of <(TSource, Boolean>)>)) 方法使用 PRedicate 对 source 中的每个元素进行测试,如果结果为 true,则生成该元素。当谓词函数对某个元素返回 false 或 source 中不再包含元素时,枚举将停止。】

两个参数的委托第一个参数表示要测试的元素。第二个参数表示 source 中元素的从零开始的索引

注意其中标红的部分:意思就是说,TakeWhile会枚举集合中的元素,通过委托的函数进行操作。但是如果中途某个元素返回false后将停止对集合中后续的元素继续枚举,并且返回的结果中包含的元素为返回False前取出的所有元素。当然当枚举完集合时,肯定也会停止继续枚举。

int[] arr1 = {10, 1, 2, 3, 4, 5};

IEnumerable<int> query = arr1.TakeWhile(Compare);

这样query中只包含10一个结果。这是因为当枚举到1返回了false,TakeWhile停止了对集合的枚举。

同样,通过Take操作,可以查询出类似SQL数据库中Top关键字的结果。如果想每次取出集合中的N个元素,我们可以arr1.Take(i*N).Except(arr1.Take((i-1)*N)。

4、Skip、SkipWhile :Skip返回从数据源中跳过某元素后的集合。

    SkipWhile需要通过委托来用于测试每个元素是否满足条件的函数。MSDN给出的解释如下:

【只要满足指定的条件,就跳过序列中的元素,然后返回剩余元素。

通过使用延迟执行实现 SkipWhile<(Of <(TSource>)>)(IEnumerable<(Of <(TSource>)>), Func<(Of <(TSource, Boolean>)>)) 方法。即时返回值为一个对象,该对象存储执行操作所需的所有信息。只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。

此方法使用 predicate 测试 source 的每个元素,如果结果为 true,则跳过该元素。谓词函数针对一个元素返回 false 后,则生成该元素及 source 中的剩余元素,并且不再调用 predicate。

如果 predicate 为序列中的所有元素返回 true,则返回一个空 IEnumerable<(Of <(T>)>)。】

注意:同TakeWhile一样,对集合中的元素进行枚举时,如果返回True则跳过此元素。如果返回False,则返回从返回False的元素开始到集合的剩余元素。即返回False时停止了对集合的枚举。如果集合中的每个元素都返回True则返回一个空的集合

如: int[] arr1 = {10, 1, 2, 3, 4, 5};var query1 = arr1.SkipWhile(n => n > 9);
            foreach ( var item in query1)
            {
                Console.WriteLine(item);
            }

输出为:1, 2, 3, 4, 5。

5、Lambda表达式

    Lambda是一个匿名函数,可以包含表达式或者语句块。它都是用Lambda运算符“=>”。念做“goes to”。如上述TakeWhile、SkipWhile都是用了  n => n > 9 Lambda表达式。在arr1.SkipWhile(n => n > 9)中,体会是n就是arr1中某一个元素,只是编译器会根据arr1定义的类型识别匿名参数n的类型。


相关文章

粤ICP备11097351号-1