当前位置: 首页 > news >正文

02020502 EF Core高级02-IQuerable会延迟执行、分部和动态构建IQuerable、IQuerable的复用

02020502 EF Core高级02-IQuerable会延迟执行、分部和动态构建IQuerable、IQuerable的复用

1. IQuerable会延迟执行(视频3-25)

1、测试一下:只查询,但是不遍历IQueryable,查看是否有执行SQL语句。
2、在查询之后、foreach前后分别加上输出语句,查看输出内容的顺序。
3、发现:只有遍历IQueryable的时候才会执行。
1.1 IQuerable使用foreach循环对比
  • 在02020409章5.2节基础上继续
// 1. 使用foreach循环
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles;foreach (var item in arts){Console.WriteLine(item.Title);}}Console.ReadLine();}}
}控制台输出:
杨中科入选中科院
微软发布.NET 10.0
微软发射微星
中国发射小行星探测器// 查看SQL语句
SELECT t.Id, t.Message, t.Title
FROM T_Articles AS t),
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 2. 不使用foreach循环
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){ using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles;}Console.ReadLine();}}
}注意,此时看不到SQL语句。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 2. 不使用foreach循环
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){ using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles;}Console.ReadLine();}}
}注意,此时看不到SQL语句。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Console.WriteLine("开始查询前");IQueryable<Article> arts = ctx.Articles; // @1 代码先查询Console.WriteLine("开始froeach");foreach (var item in arts) // @1.2 代码后foreach{Console.WriteLine(item.Title);}Console.WriteLine("完成foreach");}Console.ReadLine();}}
}控制台输出:开始查询前
开始froeach // @2.1 日志先foreachSELECT t.Id, t.Message, t.Title // 2.2 日志后查询
FROM T_Articles AS t),杨中科入选中科院
微软发布.NET 10.0
微软发射微星
中国发射小行星探测器
完成foreach说明:
1. SQL的Select语句在“开始froeach”之后。
2. 代码中先查询,后froeach;日志中先foreach再查询。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:只有遍历IQuerable的时候才会执行SQL语句。IQuerable只是构建了一个可以被执行的查询。
1.2 IQuerable简介
1、IQueryable只是代表一个“可以放到数据库服务器去执行的查询”,它没有立即执行,只是“可以被执行”而已。
2、对于IQueryable接口调用非终结方法的时候不会执行查询,而调用终结方法的时候则会立即执行查询。
3、终结方法:遍历、ToArray()、ToList()、Min()、Max()、Count()等;
4、非终结方法:GroupBy()、OrderBy()、Include()、Skip()、Take()等。
5、简单判断:一个方法的返回值类型如果是IQueryable类型,那么这个方法一般就是非终结方法,否则就是终结方法。
1.3 为什么要延迟执行
1、可以在实际执行之前,分步构建IQueryable。
2、比如:定义一个方法根据给定的关键字searchWords来查询匹配的书;如果searchAll参数是true,则书名或者作者名中含有给定的searchWords都匹配,否则只匹配书名;如果orderByPrice参数为true,则按照价格排序,否则就自然排序;upperPrice参数代表价格上限。
void QueryBooks(string searchWords, bool searchAll, bool orderByPrice,double upperPrice)
3、试着传递不同参数,查看生成的SQL的不同。
1.4 分部构建IQuerable
  • 在02020409章5.2节基础上继续
// 分部构建IQuerable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts01 = ctx.Articles.Where(a => a.Id > 1);IQueryable<Article> arts02 = arts01.Skip(2);IQueryable<Article> arts03 = arts02.Take(2);IQueryable<Article> arts04 = arts03.Where(a => a.Title.Contains("微软"));foreach (var item in arts04){Console.WriteLine(item.Title);}}Console.ReadLine();}}
}查看SQL语句:
SELECT [t0].[Id], [t0].[Message], [t0].[Title]
FROM (SELECT [t].[Id], [t].[Message], [t].[Title]FROM [T_Articles] AS [t]WHERE [t].[Id] > CAST(1 AS bigint)ORDER BY (SELECT 1)OFFSET @__p_0 ROWS FETCH NEXT @__p_0 ROWS ONLY
) AS [t0]
WHERE [t0].[Title] LIKE N'%微软%'说明:把一步步返回的数据通过SQL语言串起来了。只要没有执行终结方法,那么可以将生成的SQL语句串起来。
1.5 动态构建IQuerable
  • 在02020409章5.2节基础上继续
// Article.cs
using System.Collections.Generic;namespace OneToMany
{class Article // 文章{public long Id { get; set; }public string Title { get; set; }public string Message { get; set; }public List<Comment> Comments { get; set; } = new List<Comment>(); // 建一个空的list,而不用默认的null。public int Price { get; set; } // 增加价格}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 迁移数据库
PM> add-migration init
Build started...
Build succeeded.
To undo this action, use Remove-Migration.
PM> update-database
Build started...
Build succeeded.
Applying migration '20250926124125_adddog'.
Done.
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.cs传参形式1
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){QueryArticles("微软", true, true, 80);}Console.ReadLine();}static void QueryArticles(string searchWords, bool searchAll, bool orderByPrice, double upperPrice) {using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles.Where(a => a.Price <= upperPrice);if(searchAll){arts = arts.Where(a => a.Title.Contains(searchWords) || a.Message.Contains(searchWords));}else{arts = arts.Where(a => a.Title.Contains(searchWords));}if(orderByPrice){arts = arts.OrderBy(a => a.Price);}foreach (var item in arts){Console.WriteLine(item.Title);}}}}
}控制台输出:
微软发布.NET 10.0
微软发射微星// 查看SQL语句SELECT t.Id, t.Message, t.Price, t.TitleFROM T_Articles AS tWHERE (CAST(t.Price) AS float) <= @__upperPrice_0) && (((@__searchWords_1 LIKE N'') || (CHARINDEX(@__searchWords_1, t.Title) > 0)) || ((@__searchWords_1 LIKE N'') || (CHARINDEX(@__searchWords_1, t.Message) > 0)))ORDER BY t.Price ASC),
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.cs传参形式2
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){QueryArticles("微软", false, false, 80);}Console.ReadLine();}static void QueryArticles(string searchWords, bool searchAll, bool orderByPrice, double upperPrice) {using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles.Where(a => a.Price <= upperPrice);if(searchAll){arts = arts.Where(a => a.Title.Contains(searchWords) || a.Message.Contains(searchWords));}else{arts = arts.Where(a => a.Title.Contains(searchWords));}if(orderByPrice){arts = arts.OrderBy(a => a.Price);}foreach (var item in arts){Console.WriteLine(item.Title);}}}}
}控制台输出:
微软发布.NET 10.0
微软发射微星// SQL语句
SELECT t.Id, t.Message, t.Price, t.TitleFROM T_Articles AS tWHERE (CAST(t.Price) AS float) <= @__upperPrice_0) && ((@__searchWords_1 LIKE N'') || (CHARINDEX(@__searchWords_1, t.Title) > 0))),
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:IQuerable的延迟执行特性,使得动态的拼接查询条件变得简单。
1.6 IQuerable总结
  • IQueryable代表一个对数据库中数据进行查询的一个逻辑,这个查询是一个延迟查询。我们可以调用非终结方法向IQueryable中添加查询逻辑,当执行终结方法的时候才真正生成SQL语句来执行查询。
  • 可以实现以前要靠SQL拼接实现的动态查询逻辑。

2. IQuerable的复用(视频3-26)

  • 在本章1.5小结基础上继续
1、IQueryable是一个待查询的逻辑,因此它是可以被重复使用的。
2、IQueryable<Book> books = ctx.Books.Where(b => b.Price <= 8);
Console.WriteLine(books.Count());
Console.WriteLine(books.Max(b=>b.Price));
var books2 = books.Where(b=>b.PubTime.Year>2000);
查看生成的SQL
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace OneToMany
{class Program{static void Main(string[] args){using (MyDbContext ctx = new MyDbContext()){IQueryable<Article> arts = ctx.Articles.Where(a => a.Id > 1);Console.WriteLine(arts.Count());Console.WriteLine(arts.Max(a => a.Price));IQueryable<Article> arts2 = arts.Where(a => a.Title.Contains("微软"));arts.ToList(); // 终结方法}Console.ReadLine();}}
}// SQL语句SELECT COUNT(*)FROM [T_Articles] AS [t]WHERE [t].[Id] > CAST(1 AS bigint)SELECT MAX([t].[Price])FROM [T_Articles] AS [t]WHERE [t].[Id] > CAST(1 AS bigint)
...说明:IQuerable可以复用,在不同的方法里面调用终结方法,或者用IQuerable构建新的IQuerable的时候,IQuerable是可以复用的。

结尾

书籍:ASP.NET Core技术内幕与项目实战

视频:https://www.bilibili.com/video/BV1pK41137He

著:杨中科

ISBN:978-7-115-58657-5

版次:第1版

发行:人民邮电出版社

※敬请购买正版书籍,侵删请联系85863947@qq.com※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

http://www.hskmm.com/?act=detail&tid=25350

相关文章:

  • 在 PyCharm 中,环境:bert_env , 执行 import wandb 报错。但是,在CMD窗口,环境:bert_env , 执行 import wandb 正常。
  • Linux_T(Sticky Bit)粘滞位详解 - 详解
  • P2831 [NOIP 2016 提高组] 愤怒的小鸟 题解
  • 库存中心(三层库存模型)
  • Valley靶机渗透实战:从凭证复用到Python库劫持
  • 10.05模拟赛反思
  • MariaDB收购SkySQL增强AI与无服务器能力
  • 单片机寄存器的四种主要类型! - 实践
  • TDengine 高级特性——读缓存
  • 非合作博弈之软性均衡:东方智慧与西方理论的融合框架
  • 如何快速搭建spring-boot工程 - murphy
  • Ai元人文:东谈西论——非合作博弈之软性均衡
  • 反向传播与梯度下降:神经网络如何真正学会分类
  • Spring Cloud Alibaba微服务开发
  • OI 各种东西的板子
  • 价值弥漫:AI元人文的场域革命与共生之路
  • 做题记录 #1
  • 阿爸阿爸
  • 深度学习优化器算法巧思速览
  • 完整教程:LangChain完全指南:从入门到精通,打造AI应用开发新范式
  • NDK开发与实践(入门篇微课视频版)
  • 调了很久的代码总结
  • CF700E
  • 价值弥漫:“AI元人文”的场域革命与共生之路
  • k8s之pod概念
  • CF 1055 Div.1+Div.2
  • 2026 NOI 做题记录(五)
  • ARC 207 (Div.1)
  • “齐俊杰投资智能体”更新完了9月份的资料
  • LVS+Keepalived高可用群集 - 指南