看起来我可以将where x.a==1 && x.b==1
写成
where x.a==1
where x.b==1
据我所知,后者变成.Where(x => x.a == 1).Where(x => x.b ==1)
,但这又如何转化为数据库?哪个在优化方面会更好?我总是可以查看来自探查器的执行查询,但这不是一般化,而是更像是一个我不想依赖的经验观察。
使用反射器来浏览System.Linq命名空间是另一种选择,但是我们会错过机会让很多人不再花时间在同一件事上。如果我没有得到任何答案,我会这样做。
答案 0 :(得分:8)
好的,这是我在经过Reflector输出一段时间后的发现。在使用where
或WhereArrayIterator
时,LINQ到对象组合了连续的WhereListIterator
谓词,导致它与ALMOST的行为类似于&&运算符,但不完全是:
当您使用x.a==1 && x.b==1
时,where子句会转换为Func<TSource, bool>
,如下所示:
bool daspredicate(TSource x)
{
return x.a==1 && x.b==1
}
但是,当您使用连续的Where子句时,会有轻微的性能损失,至少从非JIT的IL方面来看。以下是组合后代码的样子:
bool predicate1(TSource x)
{
return x.a==1;
}
bool predicate2(TSource x)
{
return x.b==1;
}
bool daspredicate(TSource x)
{
return predicate1(x) && predicate2(x);
}
如您所见,这涉及额外的函数调用开销。除非JIT内联函数,否则这可能非常昂贵。我确信它做得很好,但我们现在知道,如果我们自己组合Where声明,除非必要,否则JIT的工作会变得容易得多。
但在SQL方面,查询是相同的。即使在执行之前,调试器也会将查询对象评估为相同的SQL语句。我不能在Linq命名空间中走得太远,因为事情似乎要复杂得多,但由于查询是相同的,所以不应该像上面的LINQ-to-objects示例那样受到惩罚。
编辑:我见过多个where语句在SQL Server上导致嵌套子查询的实例。我认为,只要你能够安全起见,最好坚持使用单一的语句。
答案 1 :(得分:3)
由LINQ to SQL来做正确的事情。我希望它将两个“where”子句转换为单个SQL子句,两个部分用“AND”连接在一起。
尝试两者 - 但我非常怀疑你会发现生成的SQL有任何不同。
IMO你应该总是看看生成的SQL有什么不平凡的事情,但LINQ的工作方式当然鼓励你通过用小句子编写来构建一个大型查询 - 所以我我真的希望它能够正常工作。
答案 2 :(得分:2)
DB方面它们是相同的。这只是Linq-to-SQL可组合的副作用(即,您可以从一个查询开始,然后向其添加其他条件,更改投影等)。
答案 3 :(得分:2)
代码:
where x.a==1
where x.b==1
或
where x.a==1 && x.b==1
无论如何,是C#的语法糖。它将编译为
的LINQ方法链Where(...).Where(...)
正如您猜测的那样,所以我确实怀疑生成的SQL有什么不同。尝试使用像Jetbrains的Resharper这样的工具 - 它甚至提供intellisense,让您可以选择在两者之间自动转换,以节省您重新编写测试的时间。
我的偏好是将非常简单的查询编写为方法链(例如,只涉及1个集合/表并且没有连接)以及更具表现力的Linq糖语法中更复杂的任何内容。