任何重要的LINQ方法的顺序?

时间:2010-12-16 08:30:56

标签: c# .net linq linq-to-sql

只是想知道,添加LINQ方法的顺序是否重要?

例如

using(MyDataContext context = new MyDataContext())
{
   var user = context.Users
                     .Where(u => u.UserName.StartsWith("t"))
                     .OrderByDescending(u => u.CreatedDate)
                     .FirstOrDefault();
}

完全相同?

using(MyDataContext context = new MyDataContext())
{
   var user = context.Users
                     .OrderByDescending(u => u.CreatedDate)
                     .Where(u => u.UserName.StartsWith("t"))
                     .FirstOrDefault();
}

当然,我可以逐一测试所有方法,但我想对逻辑有一些大致的了解。

所以:

  • 除了像FirstOrDefault(),ToList()和其他真正触发执行的方法之外,在LINQ语句中使用某种类型的顺序是否重要?

再次感谢!

7 个答案:

答案 0 :(得分:10)

在LINQ to SQL中,我希望这两个查询是相同的 - 至少它们应该以相同的查询计划结束,即使不是完全相同的SQL。

在LINQ to Objects中,它们的行为会有很大不同。想象一下,你有一百万用户,但只有两个用户名以“t”开头。在第一种形式中,您将过滤然后对这两个用户进行排序...在第二种形式中,它需要在开始过滤之前对所有进行排序。

当然还有其他情况下,顺序也很重要 - 特别是,如果你有一半的Select,然后是Where条款,那么你将过滤不同的事情。想象一下:

var query = Enumerable.Range(-20, 30)
                      .Select(x => -x)
                      .Where(x => x > 5);

VS

var query = Enumerable.Range(-20, 30)
                      .Where(x => x > 5)
                      .Select(x => -x);

在第一个例子中,结果将是“20,19,18,... 6”,而在第二个查询中,结果将是“-6,-7,-8,-9,-10”。非常不同!

答案 1 :(得分:4)

这取决于您使用的LINQ提供程序。对于LINQ to SQL,表达式树将在任何一种情况下解析为相同的底层SQL查询。但是,对于不太智能的提供程序,您可能会发现首先执行.Where()会更有效,因为它会在对对象进行排序之前对其进行过滤,这可能会对大量实体产生很大影响。

答案 2 :(得分:1)

我不是百分百肯定,但我认为第二个问题因为你对更大的数据集进行排序而变慢。如果您先过滤,则会删除一些元素,这样可以加快排序速度。但是,结果应该是相同的。

编辑:由于这看起来像linq-to-sql(如果您没有使用其他linq提供程序),它应该归结为在此示例中执行的相同查询。但是在某些情况下,顺序在linq-to-sql中也很重要(参见Jon的例子)。但是,100%确定的唯一方法是使用分析器来调查生成的SQL查询(但在本例中我认为没有任何区别)。

答案 3 :(得分:1)

总的来说,是的,这很重要。您可以获得不同的性能和/或不同的结果。

在您的具体示例中,订单不会更改结果。对于大多数提供程序,例如LINQ to SQL和LINQ to Entities,它也不会产生任何差别 - 将生成相同的SQL。

对于其他提供商,不同的订单可能会改变性能特征,但它的工作方式取决于具体的提供商。例如,我不认为LINQ to Objects对于两个查询都具有相同的性能。

答案 4 :(得分:1)

如何使用Sql Profiler?那将给出正确的答案。

答案 5 :(得分:1)

我认为这是关于LINQ to XXXX提供商。谁写了提供者可以说它能做什么(关于优化等)。即使可以在同一LINQ提供程序的另一个版本中提供不同的结果(仅在翻译中)。

简单来说,LINQ提供程序只是翻译器,因此您应该从现在使用的LINQ提供程序的创建者那里提出这个问题。

答案 6 :(得分:0)

可能存在性能问题。在您的情况下,第一个示例将是最好的,因为在第二个示例中,您首先在筛选之前对整个列表进行排序。您甚至可以对所有不需要的东西进行排序,然后删除不需要的部分。在第一个你删除所有你不需要的东西,然后你排序将(可能)小得多的子集。

所以对于这个确切的查询,结果是相同的,但对于大量数据,第一个将是最快的。