一·前言
Linq 英文全称Language Integrated Query,它提供了C#编程语言中的查询语法,可以使用相同的语法访问不同的数据源。并且Linq还提供了不同数据源的抽象层,所以可以使用相同的语法。本次笔记的主要内容如下:
● 用List<T>在对象上执行传统查询
● 扩展方法
● λ表达式
● LINQ 查询
● 标准查询操作符
● 表达式树
● LINQ 提供程序
一。用List<T>在对象上执行传统查询
首先我们来看一个最简单的例子,请看下面的代码:
这段代码是从strList中查找所有包含字母A的记录,并且将得到的结果进行进行从小到大的排序(如果将return a.CompareTo(b); 换成return b.CompareTo(a);结果则是从大到小的顺序进行排列了)。相信很多人用过这样的方式来对结果集进行过滤和排序操作。但是如果你想在任何集合都可以使用这两个方法,那你就可能会使用到扩展方法了。扩展方法是C#3.0的新增特性,这也是上述例子迈向LINQ 的第一个变化。下面我们就来介绍一下扩展方法。
二。扩展方法
public static class helper
上面的例子是对string进行了扩展,这样的话只要在当前命名空间下任何string对象都可以利用该扩展方法。这样会给代码带来很大的方便。
既然有了扩展方法,我们的Linq自然就很容易就出现了。就如同下面的Linq例子一样
这就是Linq最典型的样子。是不是比较像我们平时用的SQL呢?呵呵虽然还有不小的差别,但是Linq的引入实在是C#的一种革命性的变化。他不仅好用,更给枯燥的C#代码注入了一股鲜活的思想。
三。λ表达式
ding()和Select()方法之外,还可以使用λ表达式。
λ 表达式参见第7 章。λ表达式在LINQ 中非常重要,所以下面复习一下该语法。详细信息可参见第7
章。
比较λ表达式和匿名委托,会发现许多类似之处。λ运算符=>的左边是参数,不需要添加参数类型,因
为它们是由编译器解析的。λ运算符的右边定义了执行代码。在匿名方法中,需要花括号和return 语句。在
λ表达式中,不需要这些语法元素,因为它们是由编译器处理的。如果λ运算符右边有多个语句,也可以使
用花括号和return 语句。
例如下面的例子
s就像是我们在第一个例子中使用的delegate(string s)里面的s一样只是这种使用方法更加的灵活和方便。
四。LINQ 查询
我们就以NorthWind数据库为例,添加一个Linq to Sql Classes命名为Customer.dbml,然后打开Server Explorer设置好连接参数,选择Customers表直接拖拽到Customer.dbml,打开Customer.design.cs文件我们可以看到Visual Studio为我们生成了很多代码。这些代码我们会在后面的内容里详细的讲解。现在主要来讲一下Linq查询以及后面的内容。
LINQ 查询是C#语言中的一个简化查询记号。编译器编译查询表达式,调用扩展方法。查询表达式只是C#中的一个语法,但不需要修改底层的IL 代码。查询表达式必须以from子句开头,以select或group子句结束。在这两个子句之间,可以使用where、orderby、join、let 和其他from子句。注意,变量query只指定了LINQ查询。该查询不是通过这个赋值语句执行的,只要使用foreach循环访问查询,该查询就会执行。
推迟查询的执行
在运行期间定义查询表达式时,查询就不会运行。查询会在迭代数据项时运行。再看看扩展方法Where()。它使用yield return语句返回谓词为true的元素。因为使用了yield return语句,所以编译器会创建一个枚举器,在访问枚举中的项后,就返回它们。
请看一下下面的代码
var names = new List<string>{"Nino","Alberto", "Juan", "Mike", "Phil"};
其返回结果为
First iteration
Juan
Second iteration
Jack
Jim
John
Juan
但是当我们修改一下代码将 var namesWirhJ = (from name in names where name.StartsWith("J") orderby name select name);换做var namesWirhJ = (from name in names where name.StartsWith("J") orderby name select name).ToList();那么结果就成了
First iteration
Juan
Second iteration
Juan
这就是我们需要注意的地方了,每次在迭代中使用查询时,都会调用扩展方法。在大多数情况下,这是非常有效的,因为我们可以检测出源数据中的变化。但是在一些情况下,这是不可行的。调用扩展方法ToArray()、ToEnu
merable()、ToList()等可以改变这个操作。这也就是为什么我们需要演示ToList()方法了。ToList 迭代集合,返回一个实现了List<string>的集合。之后对返回的列表迭代两次,在这个过程中,数据源被修改了,但是原来的集合并没有改变。这样可以用来实现一些比较复杂的业务逻辑。
五。标准查询操作符
Where、OrderByDescending 和Select 只是LINQ 的几个查询操作符。LINQ 查询为最常用的操作符定
义了一个声明语法。还有许多标准查询操作符。下表列出了Linq的标准查询操作符。
Where OfType<TResult> |
过滤操作符定义了返回元素的条件。在Where 查询操作符中,可以使用谓词, 例如λ表达式定义的谓词,来返回布尔值。OfType<TResult>根据类型过滤元素,只 返回TResult 类型的元素 |
Select和SelectMany |
投射操作符用于把对象转换为另一个类型的对象。Select 和SelectMany 定义 了根据选择器函数选择结果值的投射 |
OrderBy,ThenBy OrderByDescending ThenByDescending Reverse |
排序操作符改变所返回的元素的顺序。OrderBy 按升序排序, OrderByDescending 按降序排序。如果第一次排序的结果很类似,就可以使用 ThenBy 和ThenBy Descending 操作符进行第二次排序。Reverse 反转集合中元 素的顺序 |
Join,GroupJoin |
连接运算符用于合并不直接相关的集合。使用Join 操作符,可以根据键选择 器函数连接两个集合,这类似于SQL 中的JOIN。GroupJoin 操作符连接两个集 合,组合其结果 |
GroupBy |
组合运算符把数据放在组中。GroupBy 操作符组合有公共键的元素 |
Any,All,Contains |
如果元素序列满足指定的条件,量词操作符就返回布尔值。Any,All 和Contains 都是量词操作符。Any 确定集合中是否有满足谓词函数的元素;All 确定集合 中的所有元素是否都满足谓词函数;Contains 检查某个元素是否在集合中。这些操作 符都返回一个布尔值 |
Take,Skip, TakeWhile SkipWhile |
分区操作符返回集合的一个子集。Take、Skip、TakeWhile 和SkipWhile 都是 分区操作符。使用它们可以得到部分结果。使用Take 必须指定要从集合中提 取的元素个数;Skip 跳过指定的元素个数,提取其他元素,TakeWhile 提取条件为真的 元素 |
Distinct,Union Intersect,Except |
Set 操作符返回一个集合。Distinct 从集合中删除重复的元素。除了Distinct 之外,其他Set 操作符都需要两个集合。Union 返回出现在其中一个集合中的 元素。Intersect 返回两个集合中都有的元素。Except 返回只出现在一个集合 中的元素 |
First FirstOrDefault Last LastOrDefault ElementAt ElementAtOrDefault Single SingleOrDefault |
这些元素操作符仅返回一个元素。First 返回第一个满足条件的元素。 FirstOrDefault 类似于First,但如果没有找到满足条件的元素,就返回类型 的默认值。Last 返回最后一个满足条件的元素。ElementAt 指定了要返回的元 素的位置。Single 只返回一个满足条件的元素。如果有多个元素都满足条件, 就抛出一个异常 |
Count,Sum,Min, Max,Average, Aggregate |
合计操作符计算集合的一个值。利用这些合计操作符,可以计算所有值的总和、 元素的个数、值最大和最小的元素,平均值等 |
ToArray ToEnumerable ToList ToDictionary toType<T> |
这些转换操作符将集合转换为数组、IEnumerable、IList、IDictionary 等 |
Empty,Range, Repeat |
这些生成操作符返回一个新集合。使用Empty,集合是空的,Range 返回一系列数 字,Repeat 返回一个始终重复一个值的集合 |
注:本文内容摘自http://blog.sina.com.cn/s/blog_5df2629a0100lr3u.html
ASP.NET开发技术交流群: 67511751(人员招募中...)