在 LINQ 中使用 2 where 子句的性能

本文关键字:where 子句 性能 LINQ | 更新日期: 2023-09-27 18:35:18

在 LINQ to-Entities 中,您可以通过执行以下操作来查询实体:

var students = SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1);

我知道在幕后,它将被转换为类似于以下内容的 SQL:

SELECT *
FROM Students
WHERE Name = 'Foo' AND Id = 1

但是,如果我写:

var students = 
    SchoolContext.Students
        .Where(s => s.Name == "Foo")
        .Where(s => s.Id == 1);

它会被转换为相同的 SQL 查询吗?据我了解.Where()将返回IEnumerable<T>,因此第二个.Where()将过滤内存中的实体,而不是将IQueryable<T>转换为SQL,这是正确的吗?

在 LINQ 中使用 2 where 子句的性能

第一个.Where()子句仍将返回一个IQueryable<T>。 只要您在IQueryable<T>上运行,它就会继续构建SQL查询,并在需要将集合放入内存时执行它(例如:如@anaximander在foreach循环或ToList()操作中使用时所述。

因此:

SchoolContext.Students.Where(s => s.Name == "Foo").Where(s => s.Id == 1);

仍然翻译成:

SELECT *
FROM Students
WHERE Name = 'Foo' AND Id = 1

虽然以下 2 个语句将转换为相同的查询:

SchoolContext.Students.Where(s => s.Name == "Foo").Where(s => s.Id == 1);
SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1);

First Where 返回IQueryable<T>因此不会有性能差异。

不,这将是相同的查询。

您可以通过流畅地链接每个 Linq 操作返回的IQueryable编写越来越复杂的查询。在评估结果之前,不会生成该语句并将其发送到服务器。

您可以通过调试并将鼠标悬停在查询上、执行ToTraceString()或使用 SQLProfiler 等工具来监视数据库服务器来检查生成的实际查询。

两者应该产生相同的 SQL; IQueryable很聪明,因为它在需要之前不会真正进行评估。第二个.Where()应该添加到第一个,然后每当您使用.ToList().Count()foreach或任何需要知道IQueryable的内容时,它将生成SQL,查询数据库并为您提供结果。

获取 Linqpad,并在那里尝试不同的查询。可以直接向实体添加连接,运行查询,并查看在每种情况下生成的 SQL。试验 Linq 的绝佳方式。