[英]IQueryable vs IEnumerable - how many DB calls?
我知道IQueryable
和IEnumerable
是如何工作的。 但是今天,当我用一个例子重新审视这些话题时。
以下是我的问题
进行了多少次数据库调用?
如果我是对的,有 2 个 DB 调用,一个使用where
子句,另一个使用Take(1)
。
public void GetEmployeesByDept(long deptId)
{
IQueryable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq == deptId);
// First DB call
var firstEmployee = empDetails.Take(1);
// Second DB call
Console.WriteLine(empDetails.GetType());
}
这是我的解释 - 但是当我将鼠标悬停在empDetails
,我可以看到该表达式包含两个参数
With the table
$x.Idseq == .Constant<TestProject.Program+<>c__DisplayClass2_0>(TestProject.Program+<>c__DisplayClass2_0).deptId
所以,现在当执行完成firstEmployee
,我将鼠标悬停在firstEmployee
变量上,我可以看到如下表达式
这也是一个数据库调用吗?
.Call System.Linq.Queryable.Take(
.Call System.Linq.Queryable.Where(
.Constant<Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Employee.Models.EmployeeDetails]>(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Employee.Models.EmployeeDetails]),
'(.Lambda #Lambda1<System.Func`2[Employee.Models.EmployeeDetails,System.Boolean]>)),
1).Lambda #Lambda1<System.Func`2[Employee.Models.EmployeeDetails,System.Boolean]>(Employee.Models.EmployeeDetails $x)
{
$x.Idseq == .Constant<TestProject.Program+<>c__DisplayClass2_0>(TestProject.Program+<>c__DisplayClass2_0).deptId
}
如果这是两者中唯一的 DB 调用,那么我为什么能够为 empDetails 加载数据?
问题#2 :现在,我将类型从IQueryable
更改为IEnumerable
。
我的理解是 DB 调用是使用where
子句进行的,然后将数据加载到内存中,然后获取第一个元素。
真的吗?
public void GetEmployeesByDept(long deptId)
{
IEnumerable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq == deptId);
// First DB call
var firstEmployee = empDetails.Take(1); // in-memory object
Console.WriteLine(empDetails.GetType());
}
如果我的理解不正确,任何人都可以纠正我。
提前致谢
检查查询执行文档
用户创建 LINQ 查询后,将其转换为命令树。 命令树是与实体框架兼容的查询的表示。 然后针对数据源执行命令树。 在查询执行时,将对所有查询表达式(即查询的所有组件)求值,包括在结果具体化中使用的那些表达式。
用户创建 LINQ 查询后
您正在以下行中创建查询
IQueryable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq == deptId);
// first DB call
var firstEmployee = empDetails.Take(1);
LINQ 查询总是在迭代查询变量时执行,而不是在创建查询变量时执行。
因此,当您访问 firstEmployee 变量时,只会进行一次调用。
IQueryable也是 IEnumerable。 所以这一行:
IEnumerable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq ==deptId);
不强制转换为 IEnumerable。 当您访问firstEmployee
变量时, empDetails
仍然是IQueryable
并将再次执行。
仅在需要时才通过执行查询进行优化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.