【.NET Core】Linq查询运算符(二)

简介: 笔记

一、概述


查询运算符是组成Linq模式的方法。这些方法中的大多数都作用于序列;其中序列指其类型实现IEnumberable接口或IQueryable接口的对象。标准查询运算符提供包括筛选、投影、集合、排序等查询功能。


查询运算符包含两组,一组作用于类型IEnumberable的对象,另一组作用于类型IQueryable的对象。


《Linq查询运算符(一)》详细介绍了筛选数据、投影运算、设置运算 、数据排序、限定符运算及数据分区本章将继续介绍。


二、生成运算


2.1 DefaultIfEmpty

返回指定序列的元素;如果序列为空,则返回单一实例集合中的类型参数的默认值。

IList<int> list = new List<int>();
var lst= list.DefaultIfEmpty();
foreach (var item in lst) 
{
    Console.WriteLine(item);
}

输出结果

0

2.2 Empty

初始化一个Empty空集合

var list=new List() 等于 var list = Enumerable.Empty();

var lst= Enumerable.Empty<int>();
foreach (var item in lst) 
{
    Console.WriteLine(item);
}


2.3 Range

Range()方法返回IEnumerable类型的集合,该集合具有指定数量的元素和从第一个元素开始的顺序值。

var lst = Enumerable.Range(5, 2);
foreach (var item in lst)
{
    Console.WriteLine(item);
}

执行结果

5
6


2.4 Repeat

Repeat()方法使用指定数量的元素生成IEnumerable类型的集合,每个元素包含相同的指定值。

var lst = Enumerable.Repeat<double>(5, 2)
foreach (var item in lst)
{
    Console.WriteLine(item);
}

执行结果

5
5


三、相等运算


3.1 SequenceEqual

两个序列,其相应元素相等且具有被视为相等的相同数量的元素

public class Person
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
}
IList<int> listA = new List<int>() { 1, 2, 3, 4 };
IList<int> listB = new List<int>() { 1, 2, 3, 4 };
IList<int> listC = new List<int>() { 2, 1, 3, 4 };
bool falg= Enumerable.SequenceEqual(listA, listB);
Console.WriteLine(falg);
bool falgC = Enumerable.SequenceEqual(listA, listC);
Console.WriteLine(falgC);
IList<Person> peopleA = new List<Person>() {
    new Person { Id = 2, Code = "002", Name = "CAZ" },
    new Person { Id = 2, Code = "002", Name = "CAZ" },
};
IList<Person> peopleB = new List<Person>() {
    new Person { Id = 2, Code = "002", Name = "CAZ" },
    new Person { Id = 2, Code = "002", Name = "CAZ" },
};
bool flagPersonA = Enumerable.SequenceEqual<Person>(peopleA, peopleB);
Console.WriteLine(flagPersonA);
bool flagPersonB = Enumerable.SequenceEqual<Person>(peopleA, peopleB, new StudentComparer());
Console.WriteLine(flagPersonB);
/// <summary>
/// 重写比较接口
/// </summary>
public class StudentComparer : IEqualityComparer<Person>
{
    public bool Equals(Person? x, Person? y)
    {
        if (x.Id == y.Id && x.Code.ToLower() == y.Code.ToLower())
           return true;
         return false;
     }
     public int GetHashCode([DisallowNull] Person obj)
     {
         return obj.GetHashCode();
      }
}


四、元素运算


元素运算从序列中返回唯一,特定的元素。


4.1 ElementAt

返回集合中指定索引处的元素。

IList<Person> peopleA = new List<Person>() {
   new Person { Id = 1, Code = "001", Name = "任峻" },
   new Person { Id = 2, Code = "002", Name = "陈矫" },
   new Person { Id = 3, Code = "003", Name = "丁仪" },
   new Person { Id = 4, Code = "004", Name = "司马朗" },
   new Person { Id = 5, Code = "005", Name = "夏侯渊" },
};
Person person= peopleA.ElementAt(4);
Console.WriteLine($"Id={person.Id},Code={person.Code},Name={person.Name}");

执行结果

Id=5,Code=005,Name=夏侯渊


4.2 ElementAtOrDefault

返回集合中指定索引处的元素;如果索引超出范围,则返回默认值。


IList<Person> peopleA = new List<Person>() {
    new Person { Id = 1, Code = "001", Name = "任峻" },
    new Person { Id = 2, Code = "002", Name = "陈矫" },
    new Person { Id = 3, Code = "003", Name = "丁仪" },
    new Person { Id = 4, Code = "004", Name = "司马朗" },
    new Person { Id = 5, Code = "005", Name = "夏侯渊" },
};
Person person= peopleA.ElementAtOrDefault<Person>(5);
Console.WriteLine($"Id={person?.Id},Code={person?.Code},Name={person?.Name}");

执行结果

Id=,Code=,Name=


4.1 First

返回集合的第一个元素或满足条件的第一个元素。

IList<Person> peopleA = new List<Person>() {
    new Person { Id = 1, Code = "001", Name = "任峻" },
    new Person { Id = 2, Code = "002", Name = "陈矫" },
    new Person { Id = 3, Code = "003", Name = "丁仪" },
    new Person { Id = 4, Code = "004", Name = "司马朗" },
    new Person { Id = 5, Code = "005", Name = "夏侯渊" },
};
Person person= peopleA.First();
Console.WriteLine($"Id={person?.Id},Code={person?.Code},Name={person?.Name}");

执行结果

Id=1,Code=001,Name=任峻


4.2 FirstOrDefault

int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
var nums = numbers.FirstOrDefault<int>(e=>e<1);
Console.WriteLine($"{ nums}");

执行结果

0


4.3 Last

返回集合的最后一个元素或满足条件的最后一个元素。

int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
var nums = numbers.Last(e=>e<5);
Console.WriteLine($"{ nums}");

执行结果

3

4.4 LastOrDefault

返回集合的最后一个元素或满足条件的最后一个元素。 如果此类元素不存在,则返回默认值。

int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
var nums = numbers.LastOrDefault(e=>e>11);
Console.WriteLine($"{ nums}");

执行结果

0

4.5 Single

返回集合的唯一一个元素或满足条件的唯一一个元素。如果没有要返回的元素或要返回多个元素,则引发InvalidOperationException。

int[] numbers = new int[] { 100};
int result = numbers.Single();
Console.WriteLine(result);

执行结果

100

4.6 SingleOrDefault

返回集合的唯一一个元素或满足条件的唯一一个元素。如果没有要返回的元素或要返回多个元素,则引发InvalidOperationException。

int[] numbers = new int[] { 100};
int result = numbers.SingleOrDefault();
Console.WriteLine(result);

执行结果

100

五、转换数据类型


转换数据类型可以通过转换方法更改输入对象的类型。名称以“As”开头的转换方法可更改源集合的静态类型但不枚举(延迟加载)此源集合。名称以“To”开头的方法可枚举(即时加载)源集合并将项放入相应的集合类型。


5.1 AsEnumerable

所有实现了IEnumerable接口的类型都可以调用此方法来获取一个IEnumerable集合。此方法一般仅用于实现类中的方法与IEnumerable接口方法重名时。

var products = db.Product.AsEnumerable()
              .Select(p => new {p.Id, p.Name, p.CreateTime.Date});

在迭代时遇见AsEnumerable()会先进行Sql查询,对已查出来的结果当然能进行Linq to object操作。


5.2 AsQueryable

AsQueryable将一个序列向下转换 一个IQueryable,它生成了一个本地查询的IQueryable包装。IQueryable实现了IEnumerable接口。但IEnumerable换成IQueryable后速度提高很多。

var query = (from item in context.Users.AsQueryable() where item.id > 10
             select item.id).ToList();


5.3 AsEnumerable和AsQueryable

1.AsEnumerable()是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First, Single, ToList…的时候)才执行。

2.AsEnumerable将一个序列向上转换为一个IEnumerable, 强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。

3.AsQueryable将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装。

4.AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。

5.ToList()立即执行。

6.当你需要操作结果的时候,用.ToList(),否则,如果仅仅是用来查询不需要进一步使用结果集,并可以延迟执行,就用.AsEnumerable()/IEnumerable /IQueryable。

7.AsEnumerable()虽然延迟执行,但还是访问数据库,而.ToList()直接取得结果放在内存中。比如我们需要显示两个部门的员工时,部门可以先取出放置在List中,然后再依次取出各个部门的员工,这时访问的效率要高一些,因为不需要每次都访问数据库去取出部门。

I8.Queryable实现了IEnumberable接口。但IEnumerable 换成IQueryable后速度提高很多。

9.IEnumerable跑的是Linq to Object,强制从数据库中读取所有数据到内存先。

5.4 Cast

将集合中的元素转换为指定类型。

DataRow row=dt.Rows.Cast<DataRow>().Single();


5.5 OfType

根据其转换为指定类型的能力筛选值。

List<object> objList = new List<object> {
     new { ID = 1, Name = "阿里" },
     new { ID = 2, Name = "百度" },
     new Person() { Id=1, Name = "马云", Code="001" }
};
var p = objList.OfType<Person>().ToList();
foreach (var item in p)
{
    Console.WriteLine(item.Name);
}


5.6 ToArray

将结合转换为数组。此方法强制执行查询。

IList<string> list = new List<string>() { "A", "B", "C" };
string[] arr= list.ToArray();


5.7 ToDictionary

根据键选择器函数将元素放入Dictionary。此方法强制执行查询。

Person[] parameters = new Person[]
{
    new Person() { Id = 1, Code = "052", Name = "正一郎" },
    new Person() { Id = 2, Code = "028", Name = "清次郎" },
    new Person() { Id = 3, Code = "020", Name = "誠三郎" },
    new Person() { Id = 4, Code = "018", Name = "征史郎" },
};
Dictionary<int, Person> dictionary = parameters.ToDictionary(value => value.Id);


5.8 ToList

将集合转换为List。此方法强制执行查询。

string[] strArr =  { "1","2", "3" };
IList<string> strList = strArr.ToList();


5.9 ToLookup

根据键选择器函数将元素放入Lookup(一对多字典)。此方法强制执行查询。该ToLookup()是不可改变,一旦创建一个Lookup,不能添加或删除元素。

IList<Person> values = new List<Person>()
{
    new Person { Id=1,Name="0001"},
    new Person { Id=2,Name="0002"},
    new Person{ Id=3,Name="0003"},
    new Person{ Id=4,Name="0004"},
};
var list = values.ToLookup(e => e.Id);
foreach (var item in list) 
{
    Console.WriteLine(item.Key);
}


目录
相关文章
|
15天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
37 5
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
1月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
41 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
23天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
25 3
|
1月前
|
XML 开发框架 .NET
.NET 9 中 LINQ 新增功能实操
.NET 9 中 LINQ 新增功能实操
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
开发框架 .NET 开发工具
.NET 9 中 LINQ 新增的功能
.NET 9 中 LINQ 新增的功能
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
51 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
82 0