[英]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.