简体   繁体   English

IQueryable 与 IEnumerable - 有多少数据库调用?

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

I know how IQueryable and IEnumerable work.我知道IQueryableIEnumerable是如何工作的。 But today while I was revisiting those topics with an example.但是今天,当我用一个例子重新审视这些话题时。

Below are my questions以下是我的问题

How many DB calls are made?进行了多少次数据库调用?

If I'm correct there are 2 DB calls, one with the where clause and the other when Take(1) is used.如果我是对的,有 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());
    }

This is my explanation - but when I hovered over the empDetails , I could see the expression contains two arguments这是我的解释 - 但是当我将鼠标悬停在empDetails ,我可以看到该表达式包含两个参数

  1. With the table

  2. $x.Idseq == .Constant<TestProject.Program+<>c__DisplayClass2_0>(TestProject.Program+<>c__DisplayClass2_0).deptId

So,now when the execution finished the firstEmployee , I hovered over the firstEmployee variable, I could see the expression as below所以,现在当执行完成firstEmployee ,我将鼠标悬停在firstEmployee变量上,我可以看到如下表达式

Is this a DB call as well?这也是一个数据库调用吗?

.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
    }

If this is the only DB call made among the two, then how come I am able to load the data for empDetails?如果这是两者中唯一的 DB 调用,那么我为什么能够为 empDetails 加载数据?

Question #2 : now, I changed the type from IQueryable to IEnumerable .问题#2 :现在,我将类型从IQueryable更改为IEnumerable

My understanding here is DB call is made with where clause and then loads the data in-memory and then takes the first element.我的理解是 DB 调用是使用where子句进行的,然后将数据加载到内存中,然后获取第一个元素。

Is that true?真的吗?

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());
}

Could anyone please correct me if my understanding is incorrect.如果我的理解不正确,任何人都可以纠正我。

Thanks in advance提前致谢

Check the Query execution documentation检查查询执行文档

After a LINQ query is created by a user , it is converted to a command tree.用户创建 LINQ 查询后,将其转换为命令树。 A command tree is a representation of a query that is compatible with the Entity Framework.命令树是与实体框架兼容的查询的表示。 The command tree is then executed against the data source.然后针对数据源执行命令树。 At query execution time, all query expressions (that is, all components of the query) are evaluated, including those expressions that are used in result materialization.在查询执行时,将对所有查询表达式(即查询的所有组件)求值,包括在结果具体化中使用的那些表达式。

After a LINQ query is created by a user用户创建 LINQ 查询后

You are creating the query in the lines below您正在以下行中创建查询

    IQueryable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq == deptId);
    // first DB call

    var firstEmployee = empDetails.Take(1);

LINQ queries are always executed when the query variable is iterated over, not when the query variable is created. LINQ 查询总是在迭代查询变量时执行,而不是在创建查询变量时执行。

So only one call is made, when you access the firstEmployee variable.因此,当您访问 firstEmployee 变量时,只会进行一次调用。

Second part explanation第二部分说明

IQueryable is also IEnumerable. IQueryable也是 IEnumerable。 So this line:所以这一行:

IEnumerable<EmployeeDetails> empDetails = _context.EmployeeDetails.Where(x => x.Idseq ==deptId);

Is not casting to IEnumerable.不强制转换为 IEnumerable。 The empDetails remains IQueryable and will be executed again, when you access the firstEmployee variable.当您访问firstEmployee变量时, empDetails仍然是IQueryable并将再次执行。

Is is optimised by executing the query, only when it is needed.仅在需要时才通过执行查询进行优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM