在EFcore中IEnumerable与IQueryable的区别

在EFcore中IEnumerable与IQueryable的区别
L X Y在EFcore中IEnumerable与IQueryable的区别
IQueryable 是 IEnumerable 的子类,所以 IQueryable 可以被转换为 IEnumerable,但是 IEnumerable 不可以被转换为 IQueryable。
IQueryable 是延迟执行的,也就是说,它不会立即执行,而是在调用 ToList()、ToArray() 等方法时才执行;而IEnumerable 是立即执行的。
同时Queryable中的where方法会返回一个IQueryable对象,而Enumerable中的where方法会返回一个IEnumerable对象。
但它们最主要的区别是一个是服务端评估,一个是客户端评估。
IEnumerable 是客户端评估,即在客户端执行,如果你要查询一条数据,而这个数据表里面一共有100万条数据,那么IEnumerable会把所有数据都拉下来,
然后在内存中过滤,CPU 和 GC 都会飙升,这样效率就很低了。
而 IQueryable 是服务端评估,即在使用SQL语句在数据库服务器上完成数据筛选,仅把最终结果返回给查询方。
IEnumerable 端
1 | [] |
IQueryable 端
1 | [] |
| 目的 | IQueryable 推荐 | IEnumerable 备注 |
|---|---|---|
| 取第一条 | FirstOrDefaultAsync(…) | 无异步版本 |
| 统计 | CountAsync(…) | 全表拉回再 Count() |
| 是否存在 | AnyAsync(…) | 全表拉回再 Any() |
其实我觉得大多数人用的应该都是FirstOrDefaultAsync(…)这个方法吧,毕竟这个挺方便的。
控制台截图(如果图床崩了加载不出来可以看文字)
IEnumerable控制台输出
1 | info: Microsoft.EntityFrameworkCore.Database.Command[20101] |
IQueryable控制台输出
1 | info: Microsoft.EntityFrameworkCore.Database.Command[20101] |
仔细看两个控制台打印的sql语句,可以发现IQueryable的sql语句中多了where子句,并且where子句的参数是 @__id_0
| 方法 | 生成 SQL | 参数 | 行数 | 评估位置 |
|---|---|---|---|---|
| IEnumerable 分支 | SELECT … FROM TestTable01s 无 WHERE | 无参数 | 全表 | 客户端(内存过滤) |
| IQueryable 分支 | SELECT … FROM TestTable01s WHERE Id = @__id_0 | 有参数 | 0~1 行 | 服务端(数据库过滤) |
IEnumerable 端
Parameters=[] 并且 SQL 里完全没有 WHERE 子句 → EF 把整个表拉回内存,再由 Enumerable.Where 在内存里筛选。
IQueryable 端
带参数 @__id_0 且 SQL 出现 WHERE [t].[Id] = @__id_0 → 过滤逻辑被翻译成 SQL,只返回匹配行,网络 IO 最小。
数据表截图:







