使用LinQ语句的正确顺序是什么?

时间:2017-10-24 21:00:17

标签: c# linq

我经常使用 LinQ 语句来查询EF,过滤数据或搜索我的数据集合,但我总是怀疑哪个是第一个写的语句

我们说我们有类似的查询:

var result = Data.Where(x => x.Text.StartsWith("ABC")).OrderBy(x => x.Id).Select(x => x.Text).Take(5).ToList();

即使语句的顺序不同,相同的查询仍然有效,例如:

var result = Data.OrderBy(x => x.Id).Select(x => x.Text).Where(x => x.Text.StartsWith("ABC")).Take(5).ToList();

我理解某些语句会修改预期结果,但我怀疑是那些不修改的语句,如前面的例子所示。是否存在指定的订单或任何良好实践指南?

2 个答案:

答案 0 :(得分:2)

它会给你不同的结果。我们假设您有以下ID:

6,5,4,3,2,1

第一个声明会给你

 1,2,3,4,5

和第二个

2,3,4,5,6

我假设所有具有以下ID的对象都以ABC

开头

编辑:我想我还没有正确回答这个问题。是,有一点不同。在第一个例子中,你只排序了5个元素,但是在第二个例子中你订购的所有元素肯定比第一个要慢。

答案 1 :(得分:1)

  

是否存在指定的订单或任何良好实践指南?

不,因为订单决定结果是什么。在SQL(一种声明性语言)中,SELECT始终位于WHERE之前,它位于GROUP BY之前,等等,并且解析引擎将其转换为执行计划,该计划将以任何顺序执行优化器认为最好。

因此选择,然后排序,然后分组全部发生在FROM子句指定的数据上,所以顺序无关紧要。

C#(在方法中)是一种过程语言,这意味着语句将按照您提供的确切顺序执行。

当您选择,然后订购时,排序适用于选择,这意味着如果您选择字段的子集(或投影到不同的字段),则排序适用于投影。如果您订购,然后选择,则排序适用于原始数据,然后投影适用于有序数据数据。

在第二个编辑过的示例中,查询似乎已被破坏,因为您指定的属性会从投影中丢失:

var result = Data.OrderBy(x => x.Id).Select(x => x.Text).Where(x => x.Text.StartsWith("ABC")).Take(5).ToList();
                                                        ^        

在这个(^)点,你只是预测Text属性,我假设sia string,因此随后的Select正在进行strings的集合,其中没有Text属性可以过滤掉。

当然你可以改变Where来直接过滤字符串,但它说明了改变命令的顺序会对查询造成灾难性的影响。它可能可能没有区别,正如您试图说明的那样,例如,排序然后过滤应该在逻辑上等同于过滤然后排序(假设一个不影响另一个),并且没有“最佳实践”可以说哪个应该先行,所以正确答案(如果有的话)将根据具体情况确定。