Linq(Language Integrated Query,集成查询语言),顾名思义就是用来查询数据的一种语言(可以看作是一组功能、框架特性的集合)。在.NETFramework3.5
(大概2007年)引入C#,用统一的C#语言快速查询各种数据,如数据库、XML文档、对象集合等等。Linq的诞生对 C# 编程领域产生了深远而持久的影响,改变了开发人员对查询的思考方式。
- 使用简单:统一语法(链式方法语法、类似SQL的查询语法),智能提示。
- 类型安全:编译时强类型检查,减少运行时错误。
- 延迟执行,查询本身只是构建了一个表达式,在真正使用的时候(foreach、ToList、查询数据库)才会执行。
- 支持多种数据源:内存中的集合,以及各种外部数据库。
Linq支持查询任何实现了IEnumerable<T>
接口的集合类型,基本上所有集合数据都支持Linq查询。如下示例:大于 5 的偶数,并倒叙排列取前三名
//方法链语法 | |
var query = arr.Where(n => n > 5 && n % 2 == 0).OrderByDescending(n => n).Take(3); |
01、Linq 基础概括
1.1、Linq语法:链式方法、查询表达式
Linq 有两种语法风格,如下实例代码,一种是常规C#方法调用方式,另外一种是类似SQL的查询表达式。这两种语法其本质是一样的,编译后的中间语言(IL)是一样的,确实仅仅只是语法形式不同而已。
🔸链式方法:就是字面意思,函数式方法调用。这些方法都来自 IEnumerable 接口或 IQueryable 接口的扩展方法,这些方法提供了过滤、聚合、排序等多种查询功能。
🔸查询表达式:查询表达式由一组用类似于 SQL 的声明性语法所编写的子句组成。 每个子句依次包含一个或多个 C# 表达式,而这些表达式可能本身就是查询表达式,或者包含查询表达式。查询表达式必须以 from
子句开头,且必须以 select
或 group
子句结尾。
//方法链语法 | |
var query = arr.Where(n => n > 5 && n % 2 == 0).OrderByDescending(n => n).Take(3); | |
//查询表达式语法,类似数据库SQL语言+C#的语法风格 | |
var query2 = (from n in arr | |
where n > 5 && n % 2 == 0 | |
orderby n descending | |
select n).Take(3); |
比较 | 链式方法 | 查询表达式(SQL) |
---|---|---|
特点 | 链式方法调用,函数式编程 | 类似SQL语句,自然语言,容易掌握 |
语法形式 | 点点点链式方法调用,Where().Select().Order() | 以from 开头:from...where...select |
常用方法/语法 | System.Linq 上提供的扩展方法或第三方扩展:Where、OrderBy、Select、Skip、Take、Union | 仅支持编译器识别的关键字:from、where、orderby、group、join、let、select、into、in、on等 |
本质 | System.Linq 提供的扩展方法调用 | 编译为标准查询运算符方法调用,编译结果和链式方法一样 |
功能完整性 | 完整的Linq功能 | 有些能力没有对应语法(如Max),需要结合链式方法使用 |
📢 两种编写方式编译后生成的IL代码实际上是一样的,也可以混合使用,因此他们并没有性能差异。
查询表达式并不能实现获取前3个元素,此时就需要两者混合使用,
var query = from u in list | |
where u.Age>14 | |
group u by u.Address into gu | |
orderby gu.Count() descending | |
select (gu.Key,gu.Count()); | |
query = query.Take(3); |
1.2、Linq执行:本地查询、解释型查询
LINQ 提供了两种用途的架构:针对本地(内存)对象的本地查询,以及针对远程数据源(数据库)的解释性查询。两者的语法形式基本一样,都支持链式方法、查询表达式。
🔸本地查询:实现了针对IEnumerable
的内存集合(数组、List)的查询,其Linq的扩展方法都在 System.Linq.Enumerable 类中。查询只是构建了一个可枚举的迭代装饰器序列,延迟在使用(消费)数据时执行。
🔸解释查询:解释查询是描述性的,实现了针对IQueryable
(Table、DbSet)的远程数据查询,对应扩展方法都在 System.Linq.Queryable 类中。他们在运行时生成表达式树,并进行解释为SQL语句,在数据库中执行该SQL语句并获取数据。