Короткий ответ: LINQ to Objects использует устойчивый алгоритм сортировки, поэтому мы можем сказать, что он детерминирован, а LINQ to SQL зависит от реализации базы данных Order By, которая обычно недетерминирована.
Детерминированный алгоритм сортировки - это тот же метод, что и на разных прогонах.
В вашем примере у вас есть дубликаты в предложении OrderBy. Для гарантированного и прогнозируемого сортировки один из предложений заказа или комбинация предложений заказа должен быть уникальным.
В LINQ вы можете достичь этого, добавив еще одно предложение OrderBy, чтобы указать свое уникальное свойство, например, в
items.OrderBy(i => i.Rate).ThenBy(i => i.ID)
.
Длинный ответ:
LINQ к объектам использует стабильную сортировку, как описано в этой ссылке: MSDN.
В LINQ to SQL это зависит от алгоритма сортировки базовой базы данных, и обычно это нестабильный тип, например, в MS SQL Server (MSDN).
В устойчивой сортировке, если ключи из двух элементов равны, порядок элементов сохраняется.Напротив, нестабильная сортировка не сохраняет порядок элементов, имеющих один и тот же ключ.
Так, LINQ к SQL, сортировка обычно недетерминирован, потому что (реляционная система управления базами данных, как MS SQL Server) RDMS может напрямую использовать алгоритм нестабильную сортировки с случайного выбора поворота или случайность может быть связана с тем, с какой базой данных происходит доступ к первой базе данных в файловой системе.
Например, представьте, что размер страницы в файловой системе может содержать до 4 строк.
страница будет полной, если вы вставите следующие данные:
Page 1
| Name | Value |
|------|-------|
| A | 1 |
| B | 2 |
| C | 3 |
| D | 4 |
Если вам нужно вставить новую строку, то RDMS имеет два варианта:
- Создать новую страницу для выделения новой строки.
- Разделить текущую страницу на две страницы. Таким образом, первая страница будет содержать имена и B и вторая страница будет держать C и D.
Предположим, что RDMS выбирает вариант 1 (для уменьшения фрагментации индекса). Если вставить новую строку с названием C и Value , вы получите:
Page 1 Page 2
| Name | Value | | Name | Value |
|------|-------| |------|-------|
| A | 1 | | C | 9 |
| B | 2 | | | |
| C | 3 | | | |
| D | 4 | | | |
Вероятно, предложение 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 , вы получите:
Page 1 Page 2
| Name | Value | | Name | Value |
|------|-------| |------|-------|
| A | 1 | | C | 3 |
| B | 2 | | D | 4 |
| C | 9 | | | |
| | | | | |
Вероятно, предложение 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
.
Вы отметили свой вопрос database
, поэтому я считаю, что вы используете LINQ to SQL. В этом случае результаты могут быть недетерминирован и вы можете получить следующее:
Результат 1:
[{"id":40, "description":"aaa", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
Результат 2:
[{"id":1, "description":"bbb", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
Если вы использовали items.OrderBy(i => i.rate).ThenBy(i => i.ID).Skip(2).Take(2);
тогда единственный возможный результат будет be:
[{"id":40, "description":"aaa", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
Если Вы не указали этот размер, тогда у нас нет гарантии. Если вы укажете несколько столбцов, например. 'order by rate, description', тогда он будет заказывать' rate', а затем, где значения 'rate' повторяются,' description'. Там может быть несколько строк с равными значениями для 'rate' и' description', и их порядок останется неопределенным. 'id' часто используется как тай-брейк, чтобы обеспечить стабильный порядок:' порядок по курсу, описание, id'. – HABO
Практическая причина, почему порядок может быть другим: некоторые быстрые алгоритмы сортировки рандомизируют выбор стержня. – usr