语言集成查询(Language-Integrated Query,LINQ)是一系列直接将查询功能集成到 C# 语言的技术统称。
随着时间的推移,人们已经为各种数据源开发了不同的语言,例如,用于关系数据库的 SQL 和用于 XML 的 XQuery。 因此,开发人员对于它们必须支持的每种数据源或数据格式,都不得不学习一种新的查询语言。LINQ 通过提供处理各种数据源和数据格式的数据的一致模型,简化了这一情况。 在 LINQ 查询中,始终会用到对象。可以使用相同的基本编码模式来查询和转换 .NET 集合、文件、字符串等对象、XML 文档和流、ADO.NET 数据集、SQL Server数据库、ADO.NET 实体框架以及 LINQ 提供程序可用的任何其它格式的数据。
1.LINQ技术分类
技术 | 说明 |
LINQ to Objects | .NET 集合、文件、字符串等对象 |
LINQ to XML | XML 文档和流 |
LINQ to DataSet(LINQ to ADO.NET) | ADO .NET 数据集 |
LINQ to SQL(LINQ to ADO.NET) | SQL Server数据库 |
LINQ to Entities(LINQ to ADO.NET) | ADO.NET 实体框架 |
2.查询表达式(Query Expression)
查询表达式必须以 from
子句开头,且必须以 select
或 group
子句结尾。在第一个 from
子句与最后一个 select
或 group
子句之间,可以包含以下这些可选子句中的一个或多个:where
, orderby
, join
, let
,甚至是其它 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.数据源
from子句中的in上下文关键字是用于指定数据源:.NET 集合、文件、字符串等对象、XML 文档和流、ADO .NET 数据集、SQL Server 数据库、ADO.NET 实体框架以及 支持 IEnumerable 或泛型 IEnumerable<T> 接口的任何对象集合等。
支持 IEnumerable<T> 或派生接口(如泛型 IQueryable<T>)的类型称为可查询类型。可查询类型不需要进行修改或特殊处理就可以用作 LINQ 数据源。
4.查询变量
查询变量是存储查询表达式而不是查询结果的任何变量。
查询变量的类型为 IEnumerable<T> 或 派生类型 IQueryable<T> 集合。
IEnumerable<T> 查询编译为委托,适用于从内存(如 List、Array)集合中查询数据,因此有利于 LINQ to Objects 和 LINQ to XML 查询。
IQueryable 和 IQueryable<T> 查询编译为表达式树,适用于从内存外(如远程数据库、服务)集合中查询数据,因此有利于 LINQ to ADO.NET 查询。
查询变量可以存储采用查询语法、方法语法或是两者的组合进行表示的查询。这两种不同的形式在语义或性能上毫无差异,在编译时,查询语法根据 C# 规范规则一定会被转换成方法语法调用。可使用查询语法表示的任何查询都可以使用方法语法进行表示,反之不一定。在大多数情况下,查询语法的可读性更高,也更为简洁。所以,我们建议在编写 LINQ 查询时尽量使用查询语法,并在必要时尽可能使用方法语法。
//查询表达式语法,简称“查询语法”
IEnumerable<City> queryMajorCities =
from city in cities
where city.Population > 100000
select city;
//标准查询运算符扩展方法语法,简称“方法语法”
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 100000);
5.查询执行
查询执行主要通过两种方式之一执行:立即执行(immediate)和延迟执行(deferred)。使用延迟执行还可以进一步分为两种类别:流式处理(streaming)和非流式处理(non-streaming)。
5.1立即执行
立即执行指的是在代码中声明查询的位置读取数据源并执行运算。返回单个不可枚举的结果的所有标准查询运算符扩展方法都立即执行。
5.2延迟执行
延迟执行指的是不在代码中声明查询的位置执行运算。仅当对查询变量进行枚举时才执行运算,例如通过使用 foreach
语句执行。这意味着,查询的执行结果取决于执行查询而非定义查询时的数据源内容。 如果多次枚举查询变量,则每次结果可能都不同。 几乎所有返回类型为 IEnumerable<T> 或 IOrderedEnumerable<TElement> 的标准查询运算符扩展方法皆以延迟方式执行。
5.2.1流式处理
流式处理运算符不需要在生成元素前读取所有源数据。在执行时,流式处理运算符一边读取每个源元素,一边对该源元素执行运算,并在可行时生成元素。流式处理运算符将持续读取源元素直到可以生成结果元素。这意味着可能要读取多个源元素才能生成一个结果元素。
5.2.2非流式处理
非流式处理运算符必须先读取所有源数据,然后才能生成结果元素。 排序或分组等运算均属于此类别。 在执行时,非流式处理查询运算符将读取所有源数据,将其放入数据结构,执行运算,然后生成结果元素。
5.3执行方式分类
6.查询表达式子句
子句 | 说明 |
---|---|
from | 范围变量(类似于可迭代变量)。 |
where | 基于由逻辑 AND 和 OR 运算符(&& 或 || )分隔的一个或多个布尔表达式筛选源元素。 |
select | 当执行查询时,指定所返回序列中元素的类型和形状。 |
group | 根据指定的键值将查询结果分组。 |
into | 可使用 into 上下文关键字创建临时标识符,将 group , join 或 select 子句的结果存储至新标识符。 |
orderby | 根据元素类型的默认比较器对查询结果进行升序或降序排序。默认升序排序。 |
join | 基于两个指定匹配条件间的相等比较而联接两个数据源。 |
let | 引入范围变量,在查询表达式中存储子表达式结果。 |
in | from子句中的上下文关键字(指定数据源)。 join 子句中的上下文关键字。 |
on | join 子句中的上下文关键字。 |
equals | join 子句中的上下文关键字。 |
by | group 子句中的上下文关键字。 |
ascending | orderby 子句中的上下文关键字。升序。 |
descending | orderby 子句中的上下文关键字。降序。 |
7.查询表达式语法
标准查询运算符扩展方法 | 查询表达式语法 |
---|---|
Cast | 使用显式类型化范围变量,例如:from int i in numbers |
GroupBy | group … by 或 group … 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 |
Select | select |
SelectMany | 多个 from 子句。 |
ThenBy<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>) | orderby …, … |
ThenByDescending<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>) | orderby …, … descending |
Where | where |
8.标准查询运算符扩展方法
8.1数据排序
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
OrderBy | 按升序对值排序。 | orderby | Enumerable.OrderBy Queryable.OrderBy |
OrderByDescending | 按降序对值排序。 | orderby … descending | Enumerable.OrderByDescending Queryable.OrderByDescending |
ThenBy | 按升序执行次要排序。 | orderby …, … | Enumerable.ThenBy Queryable.ThenBy |
ThenByDescending | 按降序执行次要排序。 | orderby …, … descending | Enumerable.ThenByDescending Queryable.ThenByDescending |
Reverse | 反转集合中元素的顺序。 | 不适用。 | Enumerable.Reverse Queryable.Reverse |
8.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 |
8.3筛选数据
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
OfType | 根据其转换为特定类型的能力选择值。 | 不适用。 | Enumerable.OfType Queryable.OfType |
Where | 选择基于谓词函数的值。 | where | Enumerable.Where Queryable.Where |
8.4量词运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
All | 确定是否序列中的所有元素都满足条件。 | 不适用。 | Enumerable.All Queryable.All |
Any | 确定序列中是否有元素满足条件。 | 不适用。 | Enumerable.Any Queryable.Any |
Contains | 确定序列是否包含指定的元素。 | 不适用。 | Enumerable.Contains Queryable.Contains |
8.5投影运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
Select | 投影基于转换函数的值。 | select | Enumerable.Select Queryable.Select |
SelectMany | 投影基于转换函数的值序列,然后将它们展平为一个序列。 | 使用多个 from 子句 | Enumerable.SelectMany Queryable.SelectMany |
Zip | 使用 2-3 个指定序列中的元素生成元组序列。 | 不适用。 | Enumerable.Zip Queryable.Zip |
8.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 |
8.7联接运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
Join | 根据键选择器函数 Join 两个序列并提取值对。 | join … in … on … equals … | Enumerable.Join Queryable.Join |
GroupJoin | 根据键选择器函数 Join 两个序列,并对每个元素的结果匹配项进行分组。 | join … in … on … equals … into … | Enumerable.GroupJoin Queryable.GroupJoin |
8.8数据分组
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
GroupBy | 对共享通用特性的元素进行分组。 每组由一个 IGrouping<TKey,TElement> 对象表示。 | group … by 或 group … by … into … | Enumerable.GroupBy Queryable.GroupBy |
ToLookup | 将元素插入基于键选择器函数的 Lookup<TKey,TElement>(一种一对多字典)。 | 不适用。 | Enumerable.ToLookup |
8.9生成运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
DefaultIfEmpty | 用默认值单一实例集合替换空集合。 | 不适用。 | Enumerable.DefaultIfEmpty Queryable.DefaultIfEmpty |
Empty | 返回一个空集合。 | 不适用。 | Enumerable.Empty |
Range | 生成包含数字序列的集合。 | 不适用。 | Enumerable.Range |
Repeat | 生成包含一个重复值的集合。 | 不适用。 | Enumerable.Repeat |
8.10相等运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
SequenceEqual | 通过以成对方式比较元素确定两个序列是否相等。 | 不适用。 | Enumerable.SequenceEqual Queryable.SequenceEqual |
8.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 |
8.12转换数据类型
方法名称 | 描述 | 查询表达式语法 | 更信息 |
---|---|---|---|
AsEnumerable | 返回类型化为 IEnumerable<T> 的输入。 | 不适用。 | Enumerable.AsEnumerable |
AsQueryable | 将(泛型)IEnumerable 转换为(泛型)IQueryable。 | 不适用。 | Queryable.AsQueryable |
Cast | 将集合中的元素转换为指定类型。 | 使用显式类型化的范围变量。 例如:from string str in words | Enumerable.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 |
8.13串联运算
方法名称 | 描述 | 查询表达式语法 | 更多信息 |
---|---|---|---|
Concat | 连接两个序列以组成一个序列。 | 不适用。 | Enumerable.Concat Queryable.Concat |
8.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 |
原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/csharp/entityframeworkcore/14366.html