要订购的目标数据如下所示:
[ {"id":40,"description":"aaa","rate":1},{"id":1,"description":"bbb",{"id":4,"description":"ccc","rate":2},{"id":19,"rate":1} ]
然后我按照房价订购商品.
奇怪的是,如果我’命令’它们,它会’跳过’某个项目的给定偏移量,然后“仅”获取部分数据.
例如,
var result = items.OrderBy(i => i.rate); var result = result.Skip(2); var result = result.Take(2);
结果看起来很好,但是“边缘情况”项目根本不会返回.
例如,
如果第一个结果回来了
[{"id":40,"rate":1}]
第二个结果回来了
[{"id":1,"rate":2}]
第二次查询调用尚未返回项“id:19”.相反,项目“id:1”已返回两次.
我的猜测是,sql OrderBy语句不会在给定属性的每次OrderBy命令时产生相同的有序列表,但是共享相同属性的组中的确切顺序可能会发生变化.
引擎盖下的确切机制是什么?
解决方法
确定性排序算法是在不同运行中始终具有相同行为的算法.
在您的示例中,OrderBy子句中有重复项.对于保证和预测排序,其中一个订单子句或订单子句的组合必须是唯一的.
在LINQ中,您可以通过添加另一个OrderBy子句来引用您的唯一属性来实现它,例如
items.OrderBy(i => i.Rate).ThenBy(i => i.ID).
答案很长:
LINQ to Objects使用稳定的排序,如此链接中所述:MSDN.
在LINQ to sql中,它取决于底层数据库的排序算法,它通常是一种不稳定的排序,就像在MS sql Server(MSDN)中一样.
在稳定的排序中,如果两个元素的键相等,则保留元素的顺序.相反,不稳定的排序不会保留具有相同键的元素的顺序.
因此,对于LINQ to sql,排序通常是不确定的,因为RDMS(关系数据库管理系统,如MS sql Server)可能直接使用带有随机数据透视选择的不稳定排序算法,或者随机性可能与数据库发生的哪一行有关首先在文件系统中访问.
如果插入以下数据,页面将填满:
Page 1 | Name | Value | |------|-------| | A | 1 | | B | 2 | | C | 3 | | D | 4 |
如果需要插入新行,RDMS有两个选项:
>创建新页面以分配新行.
>将当前页面拆分为两页.因此第一页将保留名称A和B,第二页将保存C和D.
假设RDMS选择选项1(以减少索引碎片).如果您插入名为C和Value 9的新行,您将获得:
Page 1 Page 2 | Name | Value | | Name | Value | |------|-------| |------|-------| | A | 1 | | C | 9 | | B | 2 | | | | | C | 3 | | | | | D | 4 | | | |
可能,列Name中的OrderBy子句将返回以下内容:
| Name | Value | |------|-------| | A | 1 | | B | 2 | | C | 3 | | C | 9 | -- Value 9 appears after because it was at another page | D | 4 |
现在,假设RDMS选择选项2(以增加具有许多心轴的存储系统中的插入性能).如果您插入名为C和Value 9的新行,您将获得:
Page 1 Page 2 | Name | Value | | Name | Value | |------|-------| |------|-------| | A | 1 | | C | 3 | | B | 2 | | D | 4 | | C | 9 | | | | | | | | | |
可能,列Name中的OrderBy子句将返回以下内容:
| Name | Value | |------|-------| | A | 1 | | B | 2 | | C | 9 | -- Value 9 appears before because it was at the first page | C | 3 | | D | 4 |
关于你的例子:
我相信你在你的问题中输了一些错误,因为你已经使用过items.OrderBy(i => i.rate).Skip(2).Take(2);并且第一个结果不显示Rate = 2的行.这是不可能的,因为Skip将忽略前两行并且它们具有Rate = 1,因此您的输出必须显示Rate = 2的行.
您已使用数据库标记了您的问题,因此我相信您使用的是LINQ to sql.在这种情况下,结果可能是不确定的,您可以获得以下结果:
结果1:
[{"id":40,"rate":2}]
结果2:
[{"id":1,"rate":2}]
如果你曾经使用过items.OrderBy(i => i.rate).ThenBy(i => i.ID).Skip(2).Take(2);那么唯一可能的结果是:
[{"id":40,"rate":2}]