20

I have this expression:

troubletickets = db.ServiceTickets.Include(t => t.Company).Include(t => t.UserProfile);
troubletickets.OrderByDescending(t => t.UserProfile != null ? t.UserProfile.FirstName : "ZZZ");

I have to check if UserProfile is null because if I don't I will get an error. The problem is, sometimes UserProfiles.FirstName can be null. When it is null, those values are placed at the top of the list when I order by both ascending and descending. E.g.

// Null, Null, Andy, Bill, Chris
// Null, Null, Chris, Bill, Andy

How can I alter this expression so that when I order by descending it returns something like this instead:

// Chris, Bill, Andy, Null, Null
mdk09
  • 287
  • 1
  • 4
  • 17

3 Answers3

29

You almost had it right:

troubletickets.OrderByDescending(t => t.UserProfile != null
                                      && t.UserProfile.FirstName != null
                                         ? t.UserProfile.FirstName
                                         : string.Empty);

string.Empty will always be the lowest string, so it will end up last in an OrderByDescending.

If you want something that works with both ascending and descending order, you'd have to sort in two steps:

troubletickets.OrderByDescending(t => t.UserProfile != null
                                      && t.UserProfile.FirstName != null)
              .ThenByDescending(t => t.UserProfile != null                // Or ThenBy
                                         ? t.UserProfile.FirstName
                                         : null);

This works because true > false.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
5

What you can do to handle it in the general case is to first order by whether or not the value is null, and then order based on the value itself as a tiebreaker.

troubletickets = troubletickets.OrderBy(t => t.UserProfile != null)
   .ThenByDescending(t => t.UserProfile);
Servy
  • 202,030
  • 26
  • 332
  • 449
2

You are close to it

 OrderByDescending(t => t.UserProfile != null ? t.UserProfile.FirstName : "ZZZ")

Here, you are stating that if t.userProfile is null, it should be considered as if its value was ZZZ. Just make the same for t.userProfile.FirstName.

 OrderByDescending(t => t.UserProfile != null ?
   t.UserProfile.FirstName ?? "ZZZ" :
   "ZZZ")

The "??" is the coalesce operator (if left statement is not null, use left statement, else use right statement)

SJuan76
  • 24,532
  • 6
  • 47
  • 87