I have LINQ query that is built up in a piecemeal fashion like so:
var initialQuery = from item in MyContext where xxx == yyy select item;
var furtherQuery = from item in initialQuery where bla == foo select new { some stuff };
// more code here...
// eventually:
var yetAnotherQuery = (from item in furtherQuery ...)
.OrderBy(my_condition);
// As far as I know, the following query should still maintain the order of the previous one
// see: https://stackoverflow.com/questions/911942/are-subqueries-in-linqtosql-guaranteed-to-be-in-the-same-order-as-their-parent
var stillAnotherQuery = (from item in yetAnotherQuery
select item.data_I_care_about)
.Distinct();
// And finally...
var finalQuery = stillAnotherQuery.Skip(PageIndex).Take(PageSize);
But I am getting an exception when Skip()
is called, saying that the query is not ordered!
So apparently what is indicated in my code comment above and the referenced SO question is not entirely true. In fact another SO answer indicates that the preservation of that order is not guaranteed.
Does anyone know a good way to do what I am trying to accomplish?
I considered simply including a ROW_NUMBER
in my intermediate results, and ordering by that at the very end, but I cannot find a way to get that ROW_NUMBER
in my results via LINQ.
I have seen several other SO questions trying to get the ROW_NUMBER in there, but they are all clientside, as far as I have seen.
I seem to have painted myself in a corner. Anyone know a (LINQ-friendly) way out?
Some have suggested that I do the Distinct()
before the OrderBy()
.
I believe that would give me different results.
Imagine I have this table of data
myRank | myData
-------+--------
3 | A
1 | B
2 | A
Supposing I am ordering by myRank
, and the data I care about is myData
, and imagine my original code was like this:
var query = from item in MyTable
select item;
query = query.OrderBy(item => item.myRank);
var derivedQuery = from item in query // Note: we throw away myRank
select item.myData;
derivedQuery = derivedQuery.Distinct();
If I swap the order of the OrderBy()
and Distinct()
, I will get different results. I do not want myRank
to be included in the Distinct()
.
Sorry, this is part of a much larger process, so it is hard to get all the details into this question.
But hopefully that makes sense?
Found answer on MSDN: Yes. The IGrouping<TKey, TElement> objects are yielded in an order based on the order of the elements in source that produced the first key of each IGrouping<TKey, TElement> . Elements in a grouping are yielded in the order they appear in source.
Note that the ordering is performed after the join. Although you can use an orderby clause with one or more of the source sequences before the join, generally we do not recommend it. Some LINQ providers might not preserve that ordering after the join.
Groupby preserves the order of rows within each group.
LINQ Include allows retrieving the related entities to be read from database in same query. By using the Include method we can easily read all related entities from the database in a single query.
The problem is not that the elements are no longer ordered.
Rather, the problem is that Distinct() returns a IQueryable<T>
whereas OrderBy() returns IOrderedQueryable<TSource>
, which is (apparently) required for the paging to work with EF
Swapping the Distinct() and OrderBy() steps should fix things
Edit
I suggest something roughly like this:
var query = from item in MyTable
select item;
query = query.GroupBy(item => item.myData, item => item.myRank);
var derivedQuery = query.OrderBy(group => group.Min())
.Select(group.Key);
Clarifying:
myRank
per group will effect the same order as sorting (ascending) by myRank globally first, then doing a Distinc()If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With