1.语言集成查询(Language-Integrated Query,LINQ)

语言集成查询(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 XMLXML 文档和流
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 子句之间,可以包含以下这些可选子句中的一个或多个: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.数据源

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执行方式分类

标准查询运算符扩展方法返回类型立即执行延迟的流式处理执行延迟的非流式处理执行
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

6.查询表达式子句

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

7.查询表达式语法

标准查询运算符扩展方法查询表达式语法
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

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

8.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

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选择基于谓词函数的值。whereEnumerable.Where
Queryable.Where

8.4量词运算

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

8.5投影运算

方法名称描述查询表达式语法更多信息
Select投影基于转换函数的值。selectEnumerable.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 … bygroup … 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 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

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

(0)
上一篇 2022年6月1日 21:30
下一篇 2022年6月2日 01:18

相关推荐

  • 8.Entity Framework Core数据库种子

    在 Program.cs 中添加种子初始值设定项代码。 右键单击Data文件夹或Models文件夹-添加–类-名称SeedData.cs。SeedData静态类名和Initialize静态方法名可以是任意的名称。 如果数据库中有任何学生,则不会添加任何学生并返回到种子初始值设定项继续往下…

  • 4.Entity Framework Core关系

    1.实体与属性 默认情况下,如果在类型上发现导航属性,将创建关系。 如果它指向的类型不能由当前数据库提供程序映射为标量类型,则属性被视为导航属性。 1.1主体实体 主体实体是指包含主体键/备选键属性的实体。有时被称为关系的“父级”。 1.2依赖实体 依赖实体是指包含外键属性的实体。有时被称为关系的“子级”。 1.3主体…

  • 2.Entity Framework Core配置

    1.安装依赖包 从工具菜单中选择NuGet包管理器–程序包管理器控制台 (PMC) 或 从项目菜单中选择管理NuGet程序包 或 dotnet CLI。 1.1安装EF Core数据库提供程序 安装EF Core数据库提供程序会安装 数据库驱动 和 EF Core运行时。 1.2安装 EF Core 工具 …

发表回复

登录后才能评论