David James Ball
David James Ball

Reputation: 913

Convert IQueryable to IOrderedQueryable

I have 2 tables : Items and ItemMetrics. Items contains my items and ItemMetrics contains statistics about those items.

I'm trying to sort a list of Items by the corresponding statistic Weight. I got it to work using a subquery, but I thought it was a little inefficent and could be optimized...

items.OrderBy(item => (from metric in Context.ItemMetrics where item.ItemId == metric.ItemId select metric.Weight).FirstOrDefault());

...So I am trying to accomplish the same thing using a join...

from item in items join metric in ItemMetrics on item.ItemId equals metric.ItemId orderby metric.Weight select item;

This is working fine in LINQPad. I need to return an IOrderedQueryable for a supplmentary method to do some paging using Skip and Take, but the compiler is telling me the result of this query is an IQueryable.

The only way I can think of explictly implying IOrderedQueryable is wrapping the query in

OrderBy(x => 0)

Is there a better way?

Upvotes: 3

Views: 4262

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1502286

The problem is that an IOrderedQueryable needs to be able to apply a secondary ordering - and by the time you've projected the item/metric pair to just an item, you've lost the primary ordering.

One approach would be to defer the projection until later:

var ordered = items.Join(ItemMetrics,
                         item => item.ItemId,
                         metric => metric.ItemId,
                         (item, metric) => new { item, metric })
                   .OrderBy(pair => pair.Metric.Weight);
var paged = ApplyPaging(ordered, pageConfiguration); // Whatever
var query = paged.Select(pair => pair.Item);

That's assuming ApplyPaging (or whatever you're using) returns an IQueryable or an IOrderedQueryable.

Upvotes: 5

Related Questions