语言集成查询(Language-Integrated Query,LINQ)详解

语言集成查询(Language-Integrated Query,LINQ)是一系列直接将查询功能集成到 C# 语言的技术统称。可使用统一的LINQ查询表达式查询和转换 SQL 数据库、ADO .NET 数据集、XML 文档和流以及 .NET 集合等不同的数据源中的数据。

1.LINQ技术分类

LINQ to Objects :提供一种新的处理内存中集合的方式。

LINQ to XML :提供一个支持 LINQ 的内存中 XML 编程接口。

LINQ to DataSet(LINQ to ADO.NET):提供一种针对 DataSet 的形式多样的优化查询。

LINQ to SQL(LINQ to ADO.NET):提供一种可用于直接查询 SQL Server 数据库架构的查询。

LINQ to Entities(LINQ to ADO.NET):提供一种可实现实体数据模型的查询。

2.查询表达式(Query Expression)

查询表达式必须以 from 子句开头,且必须以 select 或 group 子句结尾。在第一个 from 子句与最后一个 select 或 group 子句之间,可以包含以下这些可选子句中的一个或多个:whereorderbyjoinlet,甚至是其它 from 子句,并且任何可选子句都可以在查询正文中使用零次或多次。还可以使用 into 关键字使 join 或 group子句的结果可以充当相同查询表达式中的其它查询子句的源。

//数据源
int[] scores = { 90, 71, 82, 93, 75, 82 };

//查询表达式
IEnumerable<int> scoreQuery = //查询变量
    from score in scores //必须
    where score > 80 //可选
    orderby score descending //可选
    select score; //必须以select或group结尾

//执行查询
foreach (int testScore in scoreQuery)
{
    Console.WriteLine(testScore);
}

//输出: 93 90 82 82

3.查询变量

查询变量是存储查询表达式而不是查询结果的任何变量。

查询变量的类型为 IEnumerable<T> 或 派生类型 IQueryable<T> 集合。

IEnumerable<T> 查询编译为委托,适用于从内存(如 List、Array)集合中查询数据,因此有利于 LINQ to Objects 和 LINQ to XML 查询。

IQueryable 和 IQueryable<T> 查询编译为表达式树,适用于从内存外(如远程数据库、服务)集合中查询数据,因此有利于 LINQ to ADO.NET 查询。

查询变量可以存储采用查询语法、方法语法或是两者的组合进行表示的查询。查询语法和方法语法在语义上是相同的,在编译代码时,查询语法一定会被转换为针对 .NET 公共语言运行时 (CLR) 的方法语法。 因此,可以直接使用方法语法,而不是查询语法,但是查询语法更简单且更易于阅读。

//查询表达式语法,简称“查询语法”
IEnumerable<City> queryMajorCities =
    from city in cities
    where city.Population > 100000
    select city;

//标准查询运算符扩展方法语法,简称“方法语法”
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 100000);

4.查询表达式子句

子句说明
from指定数据源和范围变量(类似于迭代变量)。
where基于由逻辑 AND 和 OR 运算符(&& 或 ||)分隔的一个或多个布尔表达式筛选源元素。
select指定执行查询时,所返回序列中元素的类型和形状。
group根据指定的密钥值对查询结果分组。
into提供可作为对 join、group 或 select 子句结果引用的标识符。
orderby根据元素类型的默认比较器对查询结果进行升序或降序排序。默认升序排序。
join基于两个指定匹配条件间的相等比较而联接两个数据源。
let引入范围变量,在查询表达式中存储子表达式结果。
injoin 子句中的上下文关键字。
onjoin 子句中的上下文关键字。
equalsjoin 子句中的上下文关键字。
bygroup 子句中的上下文关键字。
ascendingorderby 子句中的上下文关键字。
descendingorderby 子句中的上下文关键字。

5.查询表达式语法

标准查询运算符扩展方法查询表达式语法
Cast使用显式类型化范围变量,例如:from int i in numbers
GroupBygroup … bygroup … by … into …
GroupJoin<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,IEnumerable<TInner>,TResult>)join … in … on … equals … into …
Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>)join … in … on … equals …
OrderBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>)orderby
OrderByDescending<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>)orderby … descending
Selectselect
SelectMany多个 from 子句。
ThenBy<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>)orderby …, …
ThenByDescending<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>)orderby …, … descending
Wherewhere

6.标准查询运算符扩展方法

6.1数据排序

方法名称描述查询表达式语法更多信息
OrderBy按升序对值排序。orderbyEnumerable.OrderBy
Queryable.OrderBy
OrderByDescending按降序对值排序。orderby … descendingEnumerable.OrderByDescending
Queryable.OrderByDescending
ThenBy按升序执行次要排序。orderby …, …Enumerable.ThenBy
Queryable.ThenBy
ThenByDescending按降序执行次要排序。orderby …, … descendingEnumerable.ThenByDescending
Queryable.ThenByDescending
Reverse反转集合中元素的顺序。不适用。Enumerable.Reverse
Queryable.Reverse

6.2Set运算

方法名称描述查询表达式语法更多信息
Distinct 或 DistinctBy删除集合中的重复值。不适用。Enumerable.Distinct
Enumerable.DistinctBy
Queryable.Distinct
Queryable.DistinctBy
Except 或 ExceptBy返回差集,差集指位于一个集合但不位于另一个集合的元素。不适用。Enumerable.Except
Enumerable.ExceptBy
Queryable.Except
Queryable.ExceptBy
Intersect 或 IntersectBy返回交集,交集指同时出现在两个集合中的元素。不适用。Enumerable.Intersect
Enumerable.IntersectBy
Queryable.Intersect
Queryable.IntersectBy
Union 或 UnionBy返回并集,并集指位于两个集合中任一集合的唯一的元素。不适用。Enumerable.Union
Enumerable.UnionBy
Queryable.Union
Queryable.UnionBy

6.3筛选数据

方法名称描述查询表达式语法更多信息
OfType根据其转换为特定类型的能力选择值。不适用。Enumerable.OfType
Queryable.OfType
Where选择基于谓词函数的值。whereEnumerable.Where
Queryable.Where

6.4量词运算

方法名称描述查询表达式语法更多信息
All确定是否序列中的所有元素都满足条件。不适用。Enumerable.All
Queryable.All
Any确定序列中是否有元素满足条件。不适用。Enumerable.Any
Queryable.Any
Contains确定序列是否包含指定的元素。不适用。Enumerable.Contains
Queryable.Contains

6.5投影运算

方法名称描述查询表达式语法更多信息
Select投影基于转换函数的值。selectEnumerable.Select
Queryable.Select
SelectMany投影基于转换函数的值序列,然后将它们展平为一个序列。使用多个 from 子句Enumerable.SelectMany
Queryable.SelectMany
Zip使用 2-3 个指定序列中的元素生成元组序列。不适用。Enumerable.Zip
Queryable.Zip

6.6分区数据

方法名称描述查询表达式语法更多信息
Skip跳过序列中指定位置之前的元素。不适用。Enumerable.Skip
Queryable.Skip
SkipWhile基于谓词函数跳过元素,直到元素不符合条件。不适用。Enumerable.SkipWhile
Queryable.SkipWhile
Take获取序列中指定位置之前的元素。不适用。Enumerable.Take
Queryable.Take
TakeWhile基于谓词函数获取元素,直到元素不符合条件。不适用。Enumerable.TakeWhile
Queryable.TakeWhile
Chunk将序列的元素拆分为指定最大大小的区块。不适用。Enumerable.Chunk
Queryable.Chunk

6.7联接运算

方法名称描述查询表达式语法更多信息
Join根据键选择器函数 Join 两个序列并提取值对。join … in … on … equals …Enumerable.Join
Queryable.Join
GroupJoin根据键选择器函数 Join 两个序列,并对每个元素的结果匹配项进行分组。join … in … on … equals … into …Enumerable.GroupJoin
Queryable.GroupJoin

6.8数据分组

方法名称描述查询表达式语法更多信息
GroupBy对共享通用特性的元素进行分组。 每组由一个 IGrouping<TKey,TElement> 对象表示。group … bygroup … by … into …Enumerable.GroupBy
Queryable.GroupBy
ToLookup将元素插入基于键选择器函数的 Lookup<TKey,TElement>(一种一对多字典)。不适用。Enumerable.ToLookup

6.9生成运算

方法名称描述查询表达式语法更多信息
DefaultIfEmpty用默认值单一实例集合替换空集合。不适用。Enumerable.DefaultIfEmpty
Queryable.DefaultIfEmpty
Empty返回一个空集合。不适用。Enumerable.Empty
Range生成包含数字序列的集合。不适用。Enumerable.Range
Repeat生成包含一个重复值的集合。不适用。Enumerable.Repeat

6.10相等运算

方法名称描述查询表达式语法更多信息
SequenceEqual通过以成对方式比较元素确定两个序列是否相等。不适用。Enumerable.SequenceEqual
Queryable.SequenceEqual

6.11元素运算

方法名称描述查询表达式语法更多信息
ElementAt返回集合中指定索引处的元素。不适用。Enumerable.ElementAt
Queryable.ElementAt
ElementAtOrDefault返回集合中指定索引处的元素;如果索引超出范围,则返回默认值。不适用。Enumerable.ElementAtOrDefault
Queryable.ElementAtOrDefault
First返回集合的第一个元素或满足条件的第一个元素。不适用。Enumerable.First
Queryable.First
FirstOrDefault返回集合的第一个元素或满足条件的第一个元素。 如果此类元素不存在,则返回默认值。不适用。Enumerable.FirstOrDefault
Queryable.FirstOrDefault
Queryable.FirstOrDefault<TSource>(IQueryable<TSource>)
Last返回集合的最后一个元素或满足条件的最后一个元素。不适用。Enumerable.Last
Queryable.Last
LastOrDefault返回集合的最后一个元素或满足条件的最后一个元素。如果此类元素不存在,则返回默认值。不适用。Enumerable.LastOrDefault
Queryable.LastOrDefault
Single返回集合的唯一一个元素或满足条件的唯一一个元素。 如果没有要返回的元素或要返回多个元素,则引发 InvalidOperationException不适用。Enumerable.Single
Queryable.Single
SingleOrDefault返回集合的唯一一个元素或满足条件的唯一一个元素。 如果没有要返回的元素,则返回默认值。 如果要返回多个元素,则引发 InvalidOperationException不适用。Enumerable.SingleOrDefault
Queryable.SingleOrDefault

6.12转换数据类型

方法名称描述查询表达式语法更信息
AsEnumerable返回类型化为 IEnumerable<T> 的输入。不适用。Enumerable.AsEnumerable
AsQueryable将(泛型)IEnumerable 转换为(泛型)IQueryable不适用。Queryable.AsQueryable
Cast将集合中的元素转换为指定类型。使用显式类型化的范围变量。 例如:from string str in wordsEnumerable.Cast
Queryable.Cast
OfType根据其转换为指定类型的能力筛选值。不适用。Enumerable.OfType
Queryable.OfType
ToArray将集合转换为数组。 此方法强制执行查询。不适用。Enumerable.ToArray
ToDictionary根据键选择器函数将元素放入 Dictionary<TKey,TValue>。 此方法强制执行查询。不适用。Enumerable.ToDictionary
ToList将集合转换为 List<T>。 此方法强制执行查询。不适用。Enumerable.ToList
ToLookup根据键选择器函数将元素放入 Lookup<TKey,TElement>(一对多字典)。 此方法强制执行查询。不适用。Enumerable.ToLookup

6.13串联运算

方法名称描述查询表达式语法更多信息
Concat连接两个序列以组成一个序列。不适用。Enumerable.Concat
Queryable.Concat

6.14聚合运算

方法名称描述查询表达式语法更多信息
Aggregate对集合的值执行自定义聚合运算。不适用。Enumerable.Aggregate
Queryable.Aggregate
Average计算值集合的平均值。不适用。Enumerable.Average
Queryable.Average
Count对集合中元素计数,可选择仅对满足谓词函数的元素计数。不适用。Enumerable.Count
Queryable.Count
LongCount对大型集合中元素计数,可选择仅对满足谓词函数的元素计数。不适用。Enumerable.LongCount
Queryable.LongCount
Max 或 MaxBy确定集合中的最大值。不适用。Enumerable.Max
Enumerable.MaxBy
Queryable.Max
Queryable.MaxBy
Min 或 MinBy确定集合中的最小值。不适用。Enumerable.Min
Enumerable.MinBy
Queryable.Min
Queryable.MinBy
Sum对集合中的值求和。不适用。Enumerable.Sum
Queryable.Sum

7.标准查询运算符扩展方法的执行方式

标准查询运算符扩展方法的 LINQ to Objects 实现主要通过两种方式之一执行:立即执行(immediate)和延迟执行(deferred)。使用延迟执行的标准查询运算符扩展方法可以进一步分为两种类别:流式处理(streaming)和非流式处理(non-streaming)。

7.1立即执行

立即执行指的是在代码中声明查询的位置读取数据源并执行运算。返回单个不可枚举的结果的所有标准查询运算符扩展方法都立即执行。

7.2延迟执行

延迟执行指的是不在代码中声明查询的位置执行运算。仅当对查询变量进行枚举时才执行运算,例如通过使用 foreach 语句执行。这意味着,查询的执行结果取决于执行查询而非定义查询时的数据源内容。 如果多次枚举查询变量,则每次结果可能都不同。 几乎所有返回类型为 IEnumerable<T> 或 IOrderedEnumerable<TElement> 的标准查询运算符扩展方法皆以延迟方式执行。

7.2.1流式处理

流式处理运算符不需要在生成元素前读取所有源数据。在执行时,流式处理运算符一边读取每个源元素,一边对该源元素执行运算,并在可行时生成元素。流式处理运算符将持续读取源元素直到可以生成结果元素。这意味着可能要读取多个源元素才能生成一个结果元素。

7.2.2非流式处理

非流式处理运算符必须先读取所有源数据,然后才能生成结果元素。 排序或分组等运算均属于此类别。 在执行时,非流式处理查询运算符将读取所有源数据,将其放入数据结构,执行运算,然后生成结果元素。

7.3执行方式分类

标准查询运算符扩展方法返回类型立即执行延迟的流式处理执行延迟的非流式处理执行
AggregateTSourceX
AllBooleanX
AnyBooleanX
AsEnumerableIEnumerable<T>X
AverageSingle numeric valueX
CastIEnumerable<T>X
ConcatIEnumerable<T>X
ContainsBooleanX
CountInt32X
DefaultIfEmptyIEnumerable<T>X
DistinctIEnumerable<T>X
ElementAtTSourceX
ElementAtOrDefaultTSourceX
EmptyIEnumerable<T>X
ExceptIEnumerable<T>XX
FirstTSourceX
FirstOrDefaultTSourceX
GroupByIEnumerable<T>X
GroupJoinIEnumerable<T>XX
IntersectIEnumerable<T>XX
JoinIEnumerable<T>XX
LastTSourceX
LastOrDefaultTSourceX
LongCountInt64X
MaxSingle numeric value, TSource, or TResultX
MinSingle numeric value, TSource, or TResultX
OfTypeIEnumerable<T>X
OrderByIOrderedEnumerable<TElement>X
OrderByDescendingIOrderedEnumerable<TElement>X
RangeIEnumerable<T>X
RepeatIEnumerable<T>X
ReverseIEnumerable<T>X
SelectIEnumerable<T>X
SelectManyIEnumerable<T>X
SequenceEqualBooleanX
SingleTSourceX
SingleOrDefaultTSourceX
SkipIEnumerable<T>X
SkipWhileIEnumerable<T>X
SumSingle numeric valueX
TakeIEnumerable<T>X
TakeWhileIEnumerable<T>X
ThenByIOrderedEnumerable<TElement>X
ThenByDescendingIOrderedEnumerable<TElement>X
ToArrayTSource arrayX
ToDictionaryDictionary<TKey,TValue>X
ToListIList<T>X
ToLookupILookup<TKey,TElement>X
UnionIEnumerable<T>X
WhereIEnumerable<T>X

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/experience/csharpe/14366.html

(0)
上一篇 2022年3月12日 23:27
下一篇 2022年4月4日 00:17

相关推荐

发表评论

登录后才能评论