Порядок LINQ по убыванию с нулевыми значениями в нижней части

У меня есть это выражение:

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

Я должен проверить, является ли UserProfile нулевым, потому что, если я этого не сделаю, я получу ошибку. Проблема в том, что иногда UserProfiles.FirstName может быть нулевым. Когда он равен нулю, эти значения помещаются в верхнюю часть списка, когда я заказываю как по восходящему, так и по убыванию. Например

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

Как я могу изменить это выражение так, что когда я заказываю по убыванию, он возвращает что-то вроде этого:

// Chris, Bill, Andy, Null, Null

Ответы

Ответ 1

Вы почти все правильно:

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

string.Empty всегда будет самой низкой строкой, поэтому она будет последней в OrderByDescending.

Если вы хотите что-то, что работает как с восходящим, так и с нисходящим порядком, вам придется сортировать в два этапа:

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

Это работает, потому что true > false.

Ответ 2

То, что вы можете сделать, чтобы справиться с ним в общем случае, - это первый порядок, независимо от того, является ли это значение нулевым, а затем заказывать на основе самого значения в качестве тай-брейка.

troubletickets = troubletickets.OrderBy(t => t.UserProfile != null)
   .ThenByDescending(t => t.UserProfile);

Ответ 3

Вы близко к нему

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

Здесь вы заявляете, что если t.userProfile имеет значение null, его следует рассматривать так, как если бы его значение было ZZZ. Просто сделайте то же самое для t.userProfile.FirstName.

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

"??" является оператором coalesce (если левый оператор не является нулевым, используйте левый оператор, иначе используйте правильную инструкцию)