问题
I have a Action model with Session Navigation Property,
Consider this code:
var x=db.Actions.OrderBy(p => p.Session.Number).ThenBy(p => p.Date);//it's OK
x is a ordered Action, but when grouped on x, group not iterate on x(base on Action.Session) manually on ordered enumerable:
var y=x.GroupBy(p=>p.Session).ToArray()
y have a group(Key,IGrouping) of sessions but why group.Key not ordered base on Session.Number?
How to i reached a group of Session order by number and each group ordered by date?
回答1:
Because it's Enumerable.GroupBy that preserves order. No such promise is made for Queryable.GroupBy. From the documentation of the former:
The IGrouping(Of TKey, TElement) objects are yielded in an order based on order of the elements in source that produced the first key of each IGrouping(Of TKey, TElement). Elements in a grouping are yielded in the order they appear in source.
You're calling the latter, and the above is not mentioned. Call OrderBy
after GroupBy
to make it work.
Update: since you apparently want to sort on more than just the GroupBy key, you should be able to use another GroupBy overload to specify that each session's list of actions is to be sorted:
db.Actions.GroupBy(
p => p.Session,
(session, actions) => new {
Session = session,
Actions = actions.OrderBy(p => p.Date)
}).OrderBy(p => p.Session.Number).ToArray();
回答2:
Because it is not defined that GroupBy preserves either insertion order or the underlying key order (in the same way that Dictionay<,>
makes no such guarantee, for local in-memory work). Just order after grouping, instead:
var y = db.Actions.GroupBy(p=>p.Session).OrderBy(grp => grp.Key).ToArray();
In particular, note that to translate the order directly would require it to analyse the expression to spot which parts of the ordering overlap with the grouping (and which don't), which is non-trivial.
回答3:
Thanks to @Marc Gravell & @hvd for note about groupby IGrouping(Of TKey, TElement) not preserves order of TKey but preserves order of TElement.
So my answer for my final question (How to i reached a group of Session order by number and each group ordered by date?) is:
var x= db.Actions
.OrderBy(p => p.ActionDateTime)
.GroupBy(p => p.Session)
.OrderBy(q => q.Key.Number)
.ToArray();
回答4:
Just the name GroupBy
suggests that the data queried at that moment will be grouped, aggregated (call how you want) into another data unit based on parameter provided.
In general if you want to see result sorted
the Sort()
function call should be the last one in sequence.
来源:https://stackoverflow.com/questions/8644384/why-linq-groupby-after-orderby-dismissed-order-operation