Why Linq GroupBy After OrderBy rejected the order operation?

I have an Action model with a Session add-in,

Consider this code:

var x=db.Actions.OrderBy(p => p.Session.Number).ThenBy(p => p.Date);//it OK 

x is an ordered action, but when grouped by x, the group does not iterate over x (base on Action.Session ) manually by an ordered enumeration:

 var y=x.GroupBy(p=>p.Session).ToArray() 

y have a group (Key, IGrouping) of sessions, but why is group.Key not an ordered base on Session.Number ?

How to reach a group of session orders by numbers and by each group sorted by date?

+4
source share
4 answers

Because it is Enumerable.GroupBy , which keeps order. This is not promised for Queryable.GroupBy . From the documentation of the first:

IGrouping objects (Of TKey, TElement) are displayed in an order based on the order of the elements in the source that produced the first key of each IGrouping (Of ​​TKey, TElement). Elements in the grouping are listed in the order they appear in the source.

You invoke the latter, and is not mentioned above. Call GroupBy after GroupBy to make it work.

Refresh . Since you apparently want to sort not only the GroupBy key, you can use another GroupBy overload to indicate that each list of action sessions should 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(); 
+3
source

Since it is not defined that GroupBy preserves either the insertion order or the basic order of the keys (in the same way that Dictionay<,> does not provide such a guarantee for local operation in memory). Just order after grouping, instead:

 var y = db.Actions.GroupBy(p=>p.Session).OrderBy(grp => grp.Key).ToArray(); 

In particular, note that translating an order will directly require it to parse the expression to determine which parts of the ordering overlap with the grouping (and which are not), which is nontrivial.

+2
source

Just the name GroupBy assumes that the requested data at this moment will be grouped, aggregated (call as you want) in another data block based on the provided parameter.

In general, if you want to see the result sorted , the call to the Sort() function should be the last in the sequence.

0
source

Thanks to @Marc Gravell and @hvd for a note on groupby IGrouping (Of ​​TKey, TElement) does not preserve the TKey order, but preserves the TElement order.

So, my answer to my last question (How do I reach a group of session orders by number and by each group sorted by date?) :

 var x= db.Actions .OrderBy(p => p.ActionDateTime) .GroupBy(p => p.Session) .OrderBy(q => q.Key.Number) .ToArray(); 
0
source

Source: https://habr.com/ru/post/1388119/


All Articles