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

C# 在LINQ中使用2 where子句的性能,c#,sql,linq,entity-framework,C#,Sql,Linq,Entity Framework,在LINQ to实体中,您可以通过执行以下操作来查询实体: var students = SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1); 我知道,在幕后,它将被转换为SQL,类似于: 选择* 来自学生 其中Name='Foo'和Id=1 但是,如果我写下以下内容,是否存在差异(关于性能): var students = SchoolContext.Students

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

var students = SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1);
我知道,在幕后,它将被转换为SQL,类似于:

选择*
来自学生
其中Name='Foo'和Id=1
但是,如果我写下以下内容,是否存在差异(关于性能):

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

它会被转换为同一个SQL查询吗?根据我的理解,
。Where()
将返回
IEnumerable
,因此第二个
。Where()
将过滤内存中的实体,而不是将
IQueryable
转换为SQL,对吗?

首先Where返回
IQueryable
,因此不会有性能差异。

否,它将是相同的查询

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


您可以检查通过调试并将鼠标悬停在查询上或使用类似SQLProfiler的工具监视数据库服务器生成的实际查询。

这两个工具应生成相同的SQL
IQueryable
很聪明,因为它在需要时才进行实际计算。第二个
.Where()
应该添加到第一个
.ToList()
.Count()
foreach
或者任何需要知道
IQueryable
中的内容的内容,它都会生成SQL,查询数据库并给出结果。

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

因此:

SchoolContext.Students.Where(s => s.Name == "Foo").Where(s => s.Id == 1);
仍然可以理解为:

选择*
来自学生
其中Name='Foo'和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);

获取,然后在那里尝试不同的查询。您可以直接添加到实体的连接,运行查询,并查看在每种情况下生成的SQL。使用Linq进行实验的最佳方法。

一个不使用探查器就进行调试的好方法是中断代码并将鼠标悬停在Visual Studio中的变量上,就像您在通常,您需要查看某个内容的值。当您展开它时,它会显示生成的SQL。@SLC:请注意,您所说的仅在使用现代实体框架的
DbContext
API和关联的
DbQuery
时有效。如果他使用的是
ObjectContext
和关联的
ObjectQuery
,则调用
ToTraceString
是必需的。(原因:
DbQuery
实现的
ToString
调用
ObjectQuery.ToTraceString
)。@SLC是实体框架的一个新功能吗?当我使用EF时(大约EF 3.5),这肯定不起作用-查看生成的SQL的唯一方法是将SQL探查器连接到数据库(或添加一些),可能是一个新功能,也可能是@Jean上面提到的功能。我使用的是.NET 4.5,所以我不能真正告诉您。@Danny:从.NET 3.5 SP1开始就存在了。但看起来这就是您所调用的“卷积代码”。(好吧,我想这就是为什么他们后来把它放在
ToString
调用中的原因。)