本文部分内容整理自msdn
一、LINQ的概念:
LINQ是Language Integrated Query(语言集成查询)的简称,它是集成在.NET编程语言中的一种特性,这使得查询表达式可以得到很好的编译时语法检查,丰富的元数据,智能感知等强类型语言的好处LINQ 是 Visual Studio 2008 和 .NET Framework 3.5 版中一项突破性的创新,它在对象领域和数据领域之间架起了一座桥梁。
二、LINQ出现的背景:
传统上,针对数据的查询都是以简单的字符串表示,而没有编译时类型检查或 IntelliSense 支持。此外,您还必须针对以下各种数据源学习不同的查询语言:SQL 数据库、XML 文档、各种 Web 服务等。LINQ 使查询成为 C# 和 Visual Basic 中的一等语言构造。您可以使用语言关键字和熟悉的运算符针对强类型化对象集合编写查询。在 Visual Studio 中,可以用 Visual Basic 或 C# 为以下各种数据源编写 LINQ 查询:SQL Server 数据库、XML 文档、ADO.NET 数据集以及支持 IEnumerable 或泛型 IEnumerable<T>) 接口的任意对象集合。此外,还计划了对 ADO.NET Entity Framework 的 LINQ 支持,并且第三方为许多 Web 服务和其他数据库实现编写了 LINQ 提供程序。
三、查询表达式解析:
结果为:
Numbers < 5:
4
1
3
2
0
在语义上等同于以下方法风格的查询
var lowNums = numbers
.Where(s => s < 5)
.OrderBy(s => s)
.Select(s => s);
在往下讲解之前我们先介绍些基础知识Func泛型委托,这是.net帮我们定义好的一种委托形式。
Func(T, TResult) 泛型委托:封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。写成委托的格式如下:
public delegate TResult Func<T, TResult>(T arg)
Func泛型委托总共有四种:
Func(T1, T2, TResult) 泛型委托
Func(T1, T2, T3, TResult) 泛型委托
Func(T1, T2, T3, T4, TResult) 泛型委托
Lamda表达式其实就相当于以下的匿名委托
Func<int, bool> filter = delegate(int s) { return s < 5; }; //相当于s => s < 5
Func<int, int> extract = delegate(int s) { return s; }; //相当于s => s
Func<int, int> get = delegate(int s) { return s; }; //相当于s => s
var lowNums = numbers.Where(filter).OrderBy(extract).Select(get);
where方法是一个定义于System.Linq命名空间的扩展方法
这里的predicate就是你传入的Lamda表达式,where会根据这个Lamda表达式进行数据筛选。
所有 LINQ 查询操作都由以下三个不同的操作组成:
1、获取数据源。
2、创建查询。
3、执行查询。
数据源:
在上一个示例中,由于数据源是数组,因此它隐式支持泛型 IEnumerable<T>)接口。这一事实意味着该数据源可以用 LINQ 进行查询。在 foreach 语句中执行查询,而 foreach 要求使用 IEnumerable 或 IEnumerable<T>)。支持 IEnumerable<T>)或派生接口(如泛型 IQueryable<T>)的类型称为“可查询类型”。
查询:
查询指定要从数据源中检索的信息。查询还可以指定在返回这些信息之前如何对其进行排序、分组和结构化。查询存储在查询变量中,并用查询表达式进行初始化。为使编写查询的工作变得更加容易,C# 引入了新的查询语法。上一个示例中的查询表达式包含三个子句:from、where 和 select。(如果您熟悉 SQL,您会注意到这些子句的顺序与 SQL 中的顺序相反。) from 子句指定数据源,where 子句应用筛选器,select 子句指定返回的元素的类型。目前需要注意的是,在 LINQ 中,查询变量本身不执行任何操作并且不返回任何数据。它只是存储在以后某个时刻执行查询时为生成结果而必需的信息。
执行查询:
上面例子中的foreach循环就是LINQ 的执行过程,LINQ中的执行查询分两种,强制立即执行和延迟执行,我们会在以后的部分中详细进行讲解。
四、LINQ 和泛型类型
LINQ 查询基于泛型类型,在 .NET Framework 的 2.0 版中引入了泛型类型。您无需深入了解泛型即可开始编写查询。但是,您可能需要了解两个基本概念:
1、当您创建泛型集合类(如 List<T>))的实例时,您将“T”替换为列表将包含的对象的类型。例如,字符串列表表示为 List<string>,Customer 对象列表表示为 List<Customer>。泛型列表是强类型的,且提供了比将其元素存储为 Object 的集合更多的好处。如果您尝试将 Customer 添加到 List<string>,则会在编译时出现一条错误。泛型集合易于使用的原因是您不必执行运行时类型强制转换。
2、IEnumerable<T> 是一个接口,通过该接口,可以使用 foreach 语句来枚举泛型集合类。泛型集合类支持 IEnumerable<T>),就像非泛型集合类(如 ArrayList)支持 IEnumerable。
LINQ 查询变量都实现或继承了 IEnumerable<T> 接口,如 IQueryable<T>。当您看到类型化为 IEnumerable<Customer> 的查询变量时,这只意味着在执行该查询时,该查询将生成包含零个或多个 Customer 对象的序列。