Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paginating a linq query which uses OrderBy

I want to return a list of a certain entity grouped by a certain property, ordered descending by timestamp and paginated (using Skip and Take). What I got is this:

container.CoinMessageSet.Where(
                c => c.MessageState != MessageStateType.Closed &&
                     (c.DonorOperator.OperatorCode.Equals("opcode") ||
                      c.RecipientOperator.OperatorCode.Equals("opcode"))
                ).OrderByDescending(c => c.TimeStamp)
                 .GroupBy(c => c.Reference).Skip(x).Take(100);

Upon execution I got the Exception:

The method 'Skip' is only supported for sorted input in LINQ to Entities. 
The method 'OrderBy' must be called before the method 'Skip'.

...I called OrderBy() (albeit Descending) and I called it before Skip()! What am I missing?

like image 839
HTBR Avatar asked Jan 08 '13 11:01

HTBR


People also ask

How do you do OrderBy in LINQ?

LINQ includes five sorting operators: OrderBy, OrderByDescending, ThenBy, ThenByDescending and Reverse. LINQ query syntax does not support OrderByDescending, ThenBy, ThenByDescending and Reverse. It only supports 'Order By' clause with 'ascending' and 'descending' sorting direction.

What is difference between OrderBy and ThenBy in LINQ?

The OrderBy() Method, first sort the elements of the sequence or collection in ascending order after that ThenBy() method is used to again sort the result of OrderBy() method in ascending order.

On which datasources do LINQ queries work?

In a LINQ query, you are always working with objects. You use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET Datasets, . NET collections, and any other format for which a LINQ provider is available.

How do I find the next record in LINQ?

First(); var next = items . OrderBy(item => item.Id) . First(item => item.Id > currentId); var next = items .


1 Answers

You haven't ordered the groups; you need to do that before you can page. For example:

.GroupBy(c => c.Reference).OrderBy(grp => grp.Key).Skip(x).Take(100);

(you can also substitute OrderByDescending if you want the groups in reverse order)

Also: since you are grouping, the order in the original data is largely meaningless; you could probably remove the OrderByDescending(c => c.TimeStamp).

So net result:

var query = container.CoinMessageSet.Where(
            c => c.MessageState != MessageStateType.Closed &&
                 (c.DonorOperator.OperatorCode.Equals("opcode") ||
                  c.RecipientOperator.OperatorCode.Equals("opcode"))
            ).GroupBy(c => c.Reference).OrderBy(grp => grp.Key)
             .Skip(x).Take(100);

or possibly:

var query = (from c in container.CoinMessageSet
             where c.MessageState != MessageStateType.Closed &&
                  (c.DonorOperator.OperatorCode == "opcode" ||
                   c.RecipientOperator.OperatorCode == "opcode")
             group c by c.Reference into grp
             orderby grp.Key
             select grp).Skip(x).Take(100);
like image 161
Marc Gravell Avatar answered Sep 21 '22 15:09

Marc Gravell