簡體   English   中英

IQueryable 與 IEnumerable - 有多少數據庫調用?

[英]IQueryable vs IEnumerable - how many DB calls?

我知道IQueryableIEnumerable是如何工作的。 但是今天,當我用一個例子重新審視這些話題時。

以下是我的問題

進行了多少次數據庫調用?

如果我是對的,有 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 ,我可以看到該表達式包含兩個參數

  1. With the table

  2. $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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM