在 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,这是正确的吗?
第一个.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 的绝佳方式。