本节内容,涉及4.6(P116-P130)。主要NuGet包:如前述章节

一、LINQ和EFCore的集合查询扩展方法的区别

1、LINQ和EFCore中的集合查询扩展方法,虽然命名和使用完全一样,都两者定义在不同的命名空间下,是不同的方法。PS:LINQ定义在System.Linq中,EFCore定义在Microsoft.EntityFrameworkCore中

2、我们将集合操作的扩展方法,划分为两类:①非立即执行方法,如Where、OrderBy、Select、GroupBy、Skip、Take、Include等;②立即执行方法:如Min、Max、Count、Sum、ToArray、ToList<T>、foreach等。

3、当执行非立即方法时,LINQ返回IEnumerable集合,EFCore返回IQueryable集合。两者最大区别为:LINQ会立即在服务器内存中执行计算(客户端评估);而EFCore会延迟执行,只有当我们执行立即执行方法后,EFCore才会将之前定义的所有非立即执行方法,整合为SQL抛到数据库执行(服务端评估)。

4、利用EFCore中IQueryable的特点,我们就可以充分利用客户端评估和服务端评估,达到延迟执行、简化代码、复用代码、平衡性能等目的

  1. //LINQ返回IEnumerable
  2. var nums = new int[] { 1, 2, 3, 4 };
  3. var numsNew = nums.Where(n => n > 2);
  4.  
  5. //EFCore返回IQueryable
  6. using var ctx = new MyDbContext();
  7. var books= ctx.Book.Where(a => a.Id > 0);

二、IQueryable的延迟执行案例

  1. //利用IQueryable延迟执行,拼接复杂查询
  2.  
  3. //定义一个复杂查询的方法,接受参数①关键词;②是否同时匹配书名和作者名;③是否按价格排序;④最高价格
  4. void QueryBooks(string searchWords, bool searchAll, bool orderByPrice, double upperPrice)
  5. {
  6. using var ctx = new MyDbContext();
  7.  
  8. //查询低于最高价
  9. var books = ctx.Books.Where(b => b.Price <= upperPrice);
  10.  
  11. //同时匹配书名和作者
  12. if(searchAll)
  13. {
  14. books = books.Where(b => b.Title.Contains(searchWords) || b.AuthorName.Contains(searchWords));
  15. }
  16. //只匹配书名
  17. else
  18. {
  19. books = books.Where(b =>b.Title.Contains(searchWords));
  20. }
  21.  
  22. //按照价格排序
  23. if(orderByPrice)
  24. {
  25. books = books.OrderBy(b => b.Price);
  26. }
  27.  
  28. //立即执行方法,遍历
  29. foreach(var item in books)
  30. {
  31. Console.WriteLine($"书名:{item.Title},作者:{item.AuthorName}");
  32. }
  33. }
  34.  
  35. //调用方法
  36. QueryBooks("LINQ", true, true, 30); //查询书名或作者名,按价格排序
  37. QueryBooks("LINQ", false, false, 50); //只查询书名,不按价格排序

三、复用IQueryable的案例

  1. //获得一个IQueryable集合books,并三次复用它
  2. var books = ctx.Books.Where(b => b.Price >=20);
  3.  
  4. //使用books集合,执行一次立即查询
  5. Console.WriteLine(books.Count());
  6.  
  7. //再次使用books集合,执行第二次立即查询
  8. Console.WriteLine(books.Max(b => b.Price));
  9.  
  10. //第三次立即查询
  11. foreach (var item in books.Where(b => b.PubTime.Year > 2000))
  12. {
  13. Console.WriteLine(item.Title);
  14. }

四、结合使用服务端评估和客户端评估的案例

  1. //使用立即执行方法ToList,执行SQL查询(服务端评估),将结果存到服务器的内存中
  2. var books = await ctx.Books.Take(100000).ToListAsync();
  3.  
  4. //使用服务器内存中的集合books,进行遍历查询,在服务器上执行(客户端评估)
  5. foreach (var item in books)
  6. {
  7. Console.WriteLine(item.Title);
  8. }
  9.  
  10. //由于遍历条数比较多,需要一定时间
  11. //如果在遍历过程中,我们关闭数据库服务器,程序仍然可以正常进行
  12. //说明遍历前,已经将数据下载到客户端
  13.  
  14. //大多数情况下,我们应该复用IQueryable,但在方法返回IQueryable,或嵌套遍历不同的DbSet时,需要考虑特别注意
  15.  
  16. //出错情况1:方法返回IQueryable
  17. //方法中返回IQueryable时,会销毁上下文
  18. //正确应该返回:return ctx.Books.Where(b => b.Id>5).ToList();
  19. IQueryable<Book> QueryBooks()
  20. {
  21. using var ctx = MyDbContext();
  22. return ctx.Books.Where(b => b.Id>5);
  23. }
  24.  
  25. foreach(var item in QueryBooks())
  26. {
  27. Console.WriteLine(item.Title);
  28. }
  29.  
  30. //出错情况2:嵌套遍历不同的DbSet
  31. //嵌套循环,导致两个DataReader执行,大多数数据库不允许多个DataReader同时执行
  32. var books = ctx.Books.Where(b => b.Id > 1);
  33. foreach(var item1 in books)
  34. {
  35. Console.WriteLine(item1.Title);
  36. foreach(var item2 in ctx.Authors)
  37. {
  38. Console.WriteLive(item2.Id);
  39. }
  40. }

五、最后一个综合案例:分页查询

  1. //定义一个分页查询方法,参数为获取第几页-pageIndex,每页显示几条-pageSize
  2. void OutputPage(int pageIndex, int pageSize)
  3. {
  4. using var ctx = new MyDbContext();
  5.  
  6. //获取IQueryable集合books
  7. var books = ctx.Books();
  8.  
  9. //复用books,计算集合总条数。LongCount方法和Count的功能一样
  10. long count = books.LongCount();
  11.  
  12. //按每页显示条数pageSize,计算总页数
  13. //使用了Math的Ceiling方法,如有小数,取天花板值,最后转换类型为long
  14. long pageCount = (long)Math.Ceiling(count * 1.0 / pageSize);
  15. Console.WriteLine($"总页数:{pageCount}");
  16.  
  17. //复用books,获取指定页码的数据,并遍历
  18. //使用了Skip和Take方法
  19. var pageIndexBooks = books.Skip((pageIndex - 1) * pageSize).Take(pageSize);
  20. foreach( var item in pageIndexBooks)
  21. {
  22. Console.WriteLine(item.Title)
  23. }
  24. }
  25.  
  26. //调用方法
  27. OutputPage(1,10); //第1页,每页显示10条
  28. OutputPage(3,5); //第3页,每页显示5条

特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍

快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘(IQueryable和IEnumerable)的更多相关文章

  1. 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践

    本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...

  2. 简读《ASP.NET Core技术内幕与项目实战》之3:配置

    特别说明:1.本系列内容主要基于杨中科老师的书籍<ASP.NET Core技术内幕与项目实战>及配套的B站视频视频教程,同时会增加极少部分的小知识点2.本系列教程主要目的是提炼知识点,追求 ...

  3. 《ASP.NET Core技术内幕与项目实战》精简集-目录

    本系列是杨中科2022年最新作品<ASP.NET Core技术内幕与项目实战>及B站配套视频(强插点赞)的精简集,是一个读书笔记.总结和提炼了主要知识点,遵守代码优先原则,以利于快速复习和 ...

  4. ASP.NET Core 2.0 MVC项目实战

    一.前言 毕业后入职现在的公司快有一个月了,公司主要的产品用的是C/S架构,再加上自己现在还在学习维护很老的delphi项目,还是有很多不情愿的.之前实习时主要是做.NET的B/S架构的项目,主要还是 ...

  5. ASP.NET Core中的依赖注入(5):ServicePrvider实现揭秘【补充漏掉的细节】

    到目前为止,我们定义的ServiceProvider已经实现了基本的服务提供和回收功能,但是依然漏掉了一些必需的细节特性.这些特性包括如何针对IServiceProvider接口提供一个Service ...

  6. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

  7. ASP.NET Core 2.0 : 三. 项目结构

    本章我们一起来对比着ASP.NET Framework版本看一下ASP.NET Core 2.0的项目结构.(此后的文章也尽量这样对比着, 方便学习理解.) 关注差异, 也为项目迁移做准备. 新建项目 ...

  8. ASP.NET Core Web多语言项目

    公司效益好了,准备和国外做生意,这个时候就需要多语言了. > 1. 这是一个ASP.NET Core Web多语言项目,主要展示项目的不同: > 2. 第一种:www.xxx.com/en ...

  9. Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

随机推荐

  1. Docker 10 镜像原理

    参考源 https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0 https://www.bilibili.com/vid ...

  2. Taurus.MVC 微服务框架 入门开发教程:项目部署:5、微服务应用程序发布到Docker部署(下)。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...

  3. React报错之Property 'value' does not exist on type 'HTMLElement'

    正文从这开始~ 总览 当我们试图访问一个类型为HTMLElement的元素上的value属性时,会产生"Property 'value' does not exist on type 'HT ...

  4. ZJU-199001 第三周练习 2 数字特征值 位运算算法

    题目 对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值. 对于一个整数, 从个位开始对每一位数字编号, 个位是 \(1\) 号, 十位是 \(2\) 号, 以此类推. 这个整数在第位上的数字 ...

  5. 【pytest官方文档】解读- 如何自定义mark标记,并将测试用例的数据传递给fixture函数

    在之前的分享中,我们知道可以使用yield或者return关键字把fixture函数里的值传递给test函数. 这种方法很实用,比如我在fixture函数里向数据库里插入必要的测试数据,那我就可以把相 ...

  6. KingbaseES where 条件解析顺序

    概述 KingbaseES 对于where 条件的解析严格遵守"从左到右"的原则,因此,对于选择性比较强的条件,进行最先过滤是有利于性能的. 一.KingbaseES 1.条件顺序 ...

  7. volatile 函数影响子查询提升

    我们知道 volatile 函数会影响SQL的执行性能,比如:volatile 类型函数无法建函数索引.volatile 函数针对每条记录都要执行一次.本篇的例子主要讲述 volatile 类型的函数 ...

  8. KingbaseES 全局索引

    概述:在分区表上创建的索引可分为全局索引和本地索引.全局索引包括全局非分区索引(Global Nonpartitioned Indexes)和全局分区索引(Global Partitioned Ind ...

  9. 玩转Configmap配置应用的各种姿势

    在 k8s 中使用配置主要可以有以下几种方式来实现: 1. 向容器传递命令行参数 2. 为每个容器指定自定义的环境变量 3. 通过特殊类型的卷将配置文件挂载到容器中 在 k8s 中覆盖命令行参数 和 ...

  10. 注意了!这样用 systemd 可能会有风险

    在 Linux 6 / CentOS 6 中,使用 service 来进行服务的起停,但是在 Linux 7 / CentOS 7 中,替换为使用 systemctl 命令来控制.将一些常用应用注册成 ...