LINQ OrderBy. Does it always return the same ordered list?
Short answer: LINQ to Objects uses a stable sort algorithm, so we can say that it is deterministic, and LINQ to SQL depends on the database implementation of Order By that is usually nondeterministic.
A deterministic sort algorithm is one that have always the same behavior on different runs.
In you example, you have duplicates in your OrderBy clause. For a guaranteed and predicted sort, one of the order clauses or the combination of order clauses must be unique.
In LINQ, you can achieve it by adding another OrderBy clause to refer your unique property, like initems.OrderBy(i => i.Rate).ThenBy(i => i.ID)
.
Long answer:
LINQ to Objects uses a stable sort, as documented in this link: MSDN.
In LINQ to SQL, it depends on the sort algorithm of the underlying database and it is usually an unstable sort, like in MS SQL Server (MSDN).
In a stable sort, if the keys of two elements are equal, the order of the elements is preserved. In contrast, an unstable sort does not preserve the order of elements that have the same key.
So, for LINQ to SQL, the sorting is usually nondeterministic because the RDMS (Relational Database Management System, like MS SQL Server) may directly use a unstable sort algorithm with a random pivot selection or the randomness can be related with which row the database happens to access first in the file system.
For example, imagine that the size of a page in the file system can hold up to 4 rows.
The page will be full if you insert the following data:
Page 1
| Name | Value |
|------|-------|
| A | 1 |
| B | 2 |
| C | 3 |
| D | 4 |
If you need to insert a new row, the RDMS has two options:
- Create a new page to allocate the new row.
- Split the current page in two pages. So the first page will hold the Names A and B and the second page will hold C and D.
Suppose that the RDMS chooses option 1 (to reduce index fragmentation). If you insert a new row with Name C and Value 9, you will get:
Page 1 Page 2
| Name | Value | | Name | Value |
|------|-------| |------|-------|
| A | 1 | | C | 9 |
| B | 2 | | | |
| C | 3 | | | |
| D | 4 | | | |
Probably, the OrderBy clause in column Name will return the following:
| Name | Value |
|------|-------|
| A | 1 |
| B | 2 |
| C | 3 |
| C | 9 | -- Value 9 appears after because it was at another page
| D | 4 |
Now, suppose that the RDMS chooses option 2 (to increase the insert performance in a storage system with many spindles). If you insert a new row with Name C and Value 9, you will get:
Page 1 Page 2
| Name | Value | | Name | Value |
|------|-------| |------|-------|
| A | 1 | | C | 3 |
| B | 2 | | D | 4 |
| C | 9 | | | |
| | | | | |
Probably, the OrderBy clause in column Name will return the following:
| Name | Value |
|------|-------|
| A | 1 |
| B | 2 |
| C | 9 | -- Value 9 appears before because it was at the first page
| C | 3 |
| D | 4 |
Regarding your example:
I believe that you have mistyped something in your question, because you have used items.OrderBy(i => i.rate).Skip(2).Take(2);
and the first result do not show a row with Rate = 2
. This is not possible since the Skip
will ignore the first two rows and they have Rate = 1
, so your output must show the row with Rate = 2
.
You've tagged your question with database
, so I believe that you are using LINQ to SQL. In this case, results can be nondeterministic and you could get the following:
Result 1:
[{"id":40, "description":"aaa", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
Result 2:
[{"id":1, "description":"bbb", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
If you had used items.OrderBy(i => i.rate).ThenBy(i => i.ID).Skip(2).Take(2);
then the only possible result would be:
[{"id":40, "description":"aaa", "rate":1},
{"id":4, "description":"ccc", "rate":2}]
Why does my ordered list not stay ordered?
Linq order by does not mutate the collection, it returns a new collection which is ordered. Just catch it:
YourList = YourList.OrderByDescending..
Or iterate through it :
foreach(PairODocs p in YourList.OrderByDescending..)
Linq Order by a specific number first then show all rest in order
You can use a comparison in OrderBy
or ThenBy
to perform a conditional sorting.
list.OrderByDescending(i => i == 3).ThenBy(i => i);
I use OrderByDescending
because i want matching results first(true
is "higher" than false
).
Linq OrderBy does not sort a ListT. How do I sort the list?
OrderBy
returns a query that would perform the ordering: it does not modify the original list (whereas something like List<T>.Sort
would modify the original)
Instead try something like:
ddlOptions = ddlOptions.OrderBy(l => l.DisplayText).ToList();
You might want to play around with the type of ddlOptions
or where/how you return the data as we're doing an extra ToList
than probably necessary, but that's probably a minor/non-issue for this case anyway.
Note that the same applies to other LINQ functions like GroupBy, Distinct, Concat - all return results rather than modifying the source collection.
Linq OrderBy on generic list returns not entirely alphabetical list
Could you try replacing:
IEnumerable<Word> query = words.OrderBy(x => x.Name.ToLower()).ToList();
…with:
IEnumerable<Word> query = words.OrderBy(x => x.Name,
StringComparer.InvariantCultureIgnoreCase);
There's a very small chance that it's a weird culture issue.
Order query by int from an ordered list LINQ C#
LINQ to SQL (EF) has to translate your LINQ queries into SQL that can be executed against a SQL server. What the error is trying to say, is that the .NET method of IndexOf
doesn't have a SQL equivalent. You may be best to get your data from your SoldPets
table without doing the IndexOf
part and then doing any remaining ordering away from LINQ to SQL (EF).
Something like this should work:
List<StoredPet> storedPets;
List<SoldPet> soldPets;
using (ListDataContext listDataContext = new ListDataContext())
{
using (QueryDataContext queryDataContext= new QueryDataContext())
{
storedPets =
listDataContext.StoredPets
.OrderBy(sp => sp.Name)
.Select(sp => sp.PetId)
.ToList();
soldPets =
queryDataContext.SoldPets
.ToList();
}
}
List<SoldPets> orderedSoldPets =
soldPets.OrderBy(sp => storedPets.IndexOf(sp.PetId))
Note: Your capitalisation of PetId
changes in your example, so you may wish to look at that.
Related Topics
Find Min and Max for Subsets of Consecutive Rows - Gaps and Islands
How to Emulate Repeat() in SQLite
How to Insert Random Values into a SQL Server Table
SQL Aggregate Function to Obtain a List
How Does 'In' Clause Works in Oracle
Is Using Count(*) or Select * a Good Idea
SQL Server - Invalid Characters in Parameter Names
How to Find Which Columns Don't Have Any Data (All Values Are Null)
How to Remove Part of the String in Oracle
Calculating SQL Server Row_Number() Over() for a Derived Table
Update Table with Random Record in Update Statment in SQL Server
SQL Query on Multiple Databases
How Use Inserted\Deleted Table in Stored Procedure