【问题标题】:Performance for using 2 where clauses in LINQ在 LINQ 中使用 2 个 where 子句的性能
【发布时间】:2013-10-23 00:49:58
【问题描述】:

在 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,对吗?

【问题讨论】:

    标签: c# sql linq entity-framework


    【解决方案1】:

    第一个.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);
    

    【讨论】:

    • 在不使用分析器的情况下进行调试的一种好方法是断点代码并将鼠标悬停在 Visual Studio 中的变量上,这是您通常用来查看某项值的方式。展开后它会显示生成的 SQL。
    • @SLC:请注意,您所说的仅在使用现代实体框架的DbContext API 和关联的DbQuery 时有效。如果他正在使用ObjectContext 和关联的ObjectQuery,则需要调用ToTraceString。 (原因:DbQueryToString 的实现调用ObjectQuery.ToTraceString)。
    • @SLC 这是实体框架的新功能吗?当我使用 EF(大约 EF 3.5)时,这肯定不起作用 - 查看生成的 SQL 的唯一方法是使用附加到数据库的 SQL 分析器(或添加一些convoluted code跨度>
    • 可能是一个新功能,或者可能是上面提到的@Jean 我猜。我使用的是 .NET 4.5,所以我不能告诉你。
    • @Danny:ObjectQuery.ToTraceString 自 .NET 3.5 SP1 起就存在。但看起来这就是你所说的“复杂代码”。 (嗯,我想这就是为什么他们后来把它放在ToString 电话上。)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      不,这将是同一个查询。

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

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

      【讨论】:

        【解决方案4】:

        两者应该产生相同的SQL; IQueryable 很聪明,因为它在需要时才实际评估。第二个.Where() 应该添加到第一个,然后每当您使用.ToList().Count()foreach 或任何需要知道IQueryable 中的内容in 时,它都会生成 SQL,查询数据库并给出结果。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2020-12-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多