一、有了IEnumerable 还要IQueryable干什么
普通集合的版本(IEnumerable)是在内存中过滤(客户端评估),而IQueryable版本则是把查询操作翻译成SQL语句后给数据库服务器(服务器端评估)
代码演示 一般IQueryable性能更高
二、偶尔客户端评估性能更好 作用性能优化
Every disadvantage has its advantage
eg:服务端:ctx.Comment.Select(c=>new {Id=c.Id,Pre=c.Message.Substring(0,2)+"..."});
客户端:((IEnumerable<Comments>)ctx.Comments).Select(c=>new {Id=c.Id,
Pre=c.Message.Substring(0,2)+"..."});
eg2:逻辑太复杂无法被翻译成SQL时,只能采用客户端评估,具体问题具体分析;
三、IQueryable延迟执行
代码演示
什么时候会执行IQueryable的SQL?
1、IQueryable知识代表一个“可以放到数据库服务器去执行的查询”,它没有立即执行,只是“可以被执行”而已;
2、对于IQueryable接口调用非终结方法的时候不会执行,而调用终结方法的时候则会立即执行查询
3、终结方法:遍历,ToArray(),ToList(),Min(),Max(),Count()等;
4、非终结方法:GroupBy(),OrderBy(),Include(),Skip(),Take()等
5、简单判断:一个方法的返回值类型,如果是IQueryable类型,那么这个方法一般是非终结方法,否则就是终结方法
为什么会需要延迟执行?
1、可以在实际执行之前,分布构建IQueryable;
演示
2、应用场景,根据条件不同,构建不同的IQueryable查询
总结
四、IQueryable的复用
代码演示,类似 三 中的用法
五、分页查询
1、Skip(3).Take(8),最好显示指定排序规则
2、总条数,LongCount和Count
3、页数,long PageCount = (long) Matg.ceiling(conut * 1.0/PageSize)
六、IQueryable底层是如何读取数据的
ADO.NET
1、DataReader:分批从数据库服务器读取数据,内存占用小,DB连接占用时间长;
2、DataTable:把所有数据都一次性从数据库服务器加载到客户端内存中,内存占用大,节省DB连接
验证IQueryable 用什么方式加载数据,默认用DataReader方式
·1、快速造数据
insert into User(Id,Name,Age)
select Id,Name,Age from User
2、演示加载数据过程中停掉数据库服务,会报错
如何一次性加载数据到内存中
.ToArray(),ToArrayAsync(),ToList(),ToListtAsync()等方法;
何时需要一次性加载所有数据 性能优化
场景1:遍历IQueryable 并且进行数据处理的过程很耗时;
场景2:如果方法需要返回查询结果,并且在方法里销毁DbContext的话,是不能返回IQueryable的,必须一次性加载返回;
场景3:多个IQueryable 的遍历嵌套,很多数据库的ADO.NET Core.Provider 是不支持多个DataReader同时执行的,sql server中把连接字符串中的MultipleActionResultSets=true 删掉,其他数据库不支持这个
七、EF Core中的异步方法
为什么有的方法没有异步方法?
IQueryable的异步扩展方法都是“立即执行”方法(终结方法),而像GroupBy,OrderBy,Include,Where等“非立即执行”方法(非终结方法)则没有对应的异步方法
因为“非立即执行”方法并没有实际执行SQL语句,并不是消耗IO的操作;
如何异步遍历 IQueryable
方式1:ToListAsync(),ToArrayAsync();结果集不要太大;
方式2:await foreach(Book in ctx.Books.AsAsyncEnumerable())
AsAsyncEnumerable,把IQueryable转化为异步的Enumerable在await遍历
不过,一般没必要这么做,性能优化方案