本文章是我听B站杨中科的所做的笔记
杨中科B站视频链接:.NET 6教程,.Net Core 2022视频教程,杨中科主讲_哔哩哔哩_bilibili
EF Core 基于关系的复杂查询
关系数据查询
1、查询评论中含有”微软“的所有的文章
ctx.Articles.Where(a=>a.Comments.Any(c=>c.Message.Contains("微软")));
2、查看生成的SQL语句
变换形式
1、变换成另一种写法
ctx.Comments.Where(c => c.Message.Contains("微软")).Select(c => c.Article).Distinct();
2、查看生成的SQL语句
3、同样效果的代码可能有多种写法,有时候要关注底层的SQL,看哪种方式最好
4、查询“所有由蜗牛快递负责的订单信息"
ctx.Orders.Where(o=>o.Delivery.CompanyName== "蜗牛快递");
有了IEnumerable还要IQueryable干什么
不同wherede方法
1、对普通集合和DbSet调用的Where方法,虽然用起来一样,但是”转到定义“后看到的是不同的方法
2、普通集合的版本(IEnumerable)是在内存中过滤(客户端评估),而IQueryable版本则是把查询操作翻译成SQL语句(服务端评估)
两种比较:
//IQueryable
IQueryable<Book> books = ctx.Books;
books.Where(b => b.Price > 1.1)
//IEnumerable
IEnumerable<Book> books = ctx.Books;
books.Where(b => b.Price > 1.1)
客户端评估有时候也很可爱
”客户端评估"有可能引起性能问题,所以要尽量避免。但是凡事都是优缺点并存的,没有绝对的好东西,也没有绝对的坏东西,有时候我们使用“客户端评估”反而能带来性能的提升
//服务端评估
IQueryable<Book> books = ctx.Books.Where(b=>b.Price>1.1);
var items = books.Select(b=>new {TitlePre=b.Title.Substring(0,2),PubYear=b.PubTime.Year});
//客户端评估
IEnumerable<Book> books = ctx.Books.Where(b => b.Price > 1.1);
var items = books.Select(b=>new {TitlePre=b.Title.Substring(0,2),PubYear=b.PubTime.Year});
IQueryable的延迟执行
1、测试一下:只查询,但是不遍历IQueryable,查看是否由执行SQL语句
2、在查询之后,foreach前后分别加上输出语句,查看输出内容的顺序
3、发现:只有遍历IQueryable的时候才会执行
4、“IQueryable”的意思是“可查询的”,可以查询、但是没有执行查询,查询的执行被延迟了。
所谓IQueryable:
1、IQueryable只是代表一个“可以放到数据库服务器去执行的查询”,它没有立即执行,只是“可以被执行”而已
2、对于IQueryable接口调用非终结方法的时候不会执行查询,而调用终结方法的时候则会立即执行查询
3、终结方法:遍历、ToArray()、ToList()、Min()、Max()、Count()等
4、非终结方法:GroupBy()、OrderBy()、Include()、Skip()、Task()等
5、简单判断:一个方法的返回值类型如果是IQueryable类型,那么这个方法一般就是非终结方法,否则就是终结方法
为什么延迟执行:
1、可以在实际执行之前,分步构建IQueryable
2、比如:定义一个方法根据给定的关键字searchWords来查询匹配的书;如果searchAll参数是true,则书名或者作者名中含有给定的searchWords都匹配,否则只匹配书名;如果orderByPrice参数为true,则按照价格排序,否则就自然排序;upperPrice参数代表价格上限
void QueryBooks(string searchWords, bool searchAll, bool orderByPrice,double upperPrice)
3、试着传递不同的参数,查看生成的SQL的不同
结论:
1、IQueryable代表一个对数据库中数据进行查询的一个逻辑,这个查询是一个延迟查询。我们可以调用非终结方法向IQueryable中添加查询逻辑,当执行终结方法的时候才真正生成SQL语句来执行查询
2、可以实现以前要靠SQL拼接实现的动态查询逻辑
IQueryable复用
1、IQueryable是一个待查询的逻辑,因此它是可以被重复使用的
IQueryable<Book> books = ctx.Books.Where(b => b.Price <= 8);
Console.WriteLine(books.Count());
var books2 = books.Where(b=>b.PubTime.Year>2000