I'm trying to sort some data that can be in one of the following (inferred) states (in this order):
live
(valid StartDate
, null EndDate
);draft
(null StartDate
);ended
(valid EndDate
).I've inherited the following syntax on a IQueryable
:
iQueryableData
.OrderBy(t => t.StartDate == null ? 1 : (t.EndDate == null ? 0 : 2))
.ThenByDescending(t => t.StartDate)
.ThenBy(t => t.PartnerId)
And that is fine, since it sorts on one of the first 3 columns of the table, depending on some IF
statements.
Now I need to rewrite that to work in memory (so just LINQ
, no IQueryable
), on a different (but similar) model. Here's what the above query will roughly translate to:
data
.OrderBy(t => t.StartDate == null
? t.EndDate // DateTime
: (t.EndDate == null
? t.Id // integer
: t.Name // string
)
)
This obviously fails to compile, because
CS0173 C# Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and 'string'
Presumably, I could keep sorting by an integer, but I've no idea what the numbers would refer to in this case (the order of the property as written inside the class? The sorted by name order of the same thing?).
Unfortunately, all questions I've found related to mine are ordering based on an IF
statement that's relying on an external value (not inside the data).
Use the ThenBy extension. This ensures that the previous order is maintained while applying a new order criteria. For each specific case return the desired property to participate in order (Name, Id, EndDate) so each group in the set will be sorted by these values. Use some constant value for the other items that do not meet the original criteria so their order remains unchanged by the current ThenBy.
items
//sort by live, draft and ended
.OrderBy(t => t.StartDate == null ? 1 : (t.EndDate == null ? 0 : 2))
//keep the live, draft and ended sort,
//and for the live items apply only a sort by ID,
//but let the other items in the previous order (live, draft and ended)
//by returning the same value for each (zero or null)
.ThenBy( t=> t.StartDate != null && t.EndDate == null ? t.ID : 0)
//the same
//keep the sort by live, draft, ended and now by ID for live ones only
//but for the draft items sort them by EndDate
//leave the others unaffected by this sort
.ThenBy( t=> t.StartDate == null && t.EndDate != null ? t.EndDate : default(DateTime?))
//same - sort ended items by name
.ThenBy( t=> t.StartDate != null && t.EndDate != null ? t.Name : null)
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