首页 > 解决方案 > 为什么添加两个 .OrderBy(或 .OrderByDescending)语句会以相反的顺序应用排序?

问题描述

我在今天重构的一些代码中遇到了以下内容。

context.Entities.Where(x => x.ForeignKeyId == id)
    .OrderBy(x => x.FirstSortField)
    .OrderBy(x => x.SecondSortField);

最初,我.OrderBy(x => x.FirstSortField)认为第一个 OrderBy 语句将被第二个 OrderBy 替换。经过测试,我意识到它正在将 SQL 生成为ORDER BY SecondSortField, FirstSortField.

因此,等价的实际上是:

context.Entities.Where(x => x.ForeignKeyId == id)
    .OrderBy(x => x.SecondSortField)
    .ThenBy(x => x.FirstSortField);

谁能解释 EF6 这样做的原因?在我看来,用第二个排序字段替换第一个排序字段会更直观。

标签: c#sql-serverlinq-to-sql

解决方案


这都是就本地数据而言的,但 EF 希望在构建表达式树和编写查询时进行逻辑等效。

你应该研究一下稳定排序的概念。当您使用稳定的排序算法时,相等项目的原始顺序将被保留。

因此,假设您有这样的数据,其中包含明显的名字/姓氏字段:

布拉德·琼斯
汤姆史密斯
山姆·琼斯
吉姆·多伊
詹姆斯·史密斯
瑞恩史密斯

如果您最初仅按名字订购,您会得到:

布拉德·琼斯
詹姆斯·史密斯
吉姆·多伊
瑞恩史密斯
山姆·琼斯
汤姆史密斯

如果您现在采用此排序列表,并再次按姓氏排序,您将获得按两个字段排序的结果,其中稍后的排序优先于先前的排序......但只有在排序稳定时,您才能保证确切的顺序

吉姆·多伊
布拉德·琼斯
山姆·琼斯
詹姆斯·史密斯
瑞恩史密斯
汤姆史密斯

这给我们带来了 .Net 使用什么算法以及它是否稳定的问题。我们去的文档,我们在备注部分找到这个:

此方法执行稳定排序

具体算法这里没有记录。我相信这是一个Quicksort,但将其排除在文档之外可能是有意的,以允许维护人员在发现更好的东西时更新满足稳定性要求的最佳可用选项。

但是,同样,这是针对本地数据的。数据库将按照 SQL 的指示进行操作。


推荐阅读