172 votes

LINQ commande par colonne null où l'ordre est croissant et les valeurs null devrait être la dernière

Je suis en train de trier une liste de produits, de par leur prix.

Le résultat de définir les besoins de la liste des produits par prix, du bas en haut par la colonne LowestPrice. Toutefois, cette colonne est nullable.

Je peux trier la liste dans l'ordre décroissant comme suit:

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null

Cependant je ne peux pas comprendre comment trier ce dans l'ordre croissant.

// i'd like: 100, 101, 102, null, null

184voto

DaveShaw Points 19555

Essayez de mettre les deux colonnes de la même orderby.

orderby p.LowestPrice.HasValue descending, p.LowestPrice

Sinon, chaque orderby est une opération distincte sur la collection re-commande à chaque fois.

Cela devrait l'ordre ceux avec une valeur d'abord, puis " l'ordre de la valeur.

105voto

Jason Points 125291

Il aide vraiment à comprendre la syntaxe de requête LINQ et comment il est traduit à LINQ appels de méthode.

Il s'avère que

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;

sera traduite par le compilateur

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);

Ce n'est absolument pas ce que vous voulez. Il trie par Product.LowestPrice.HasValue en descending commande et de la re-trie l'intégralité de la collection en Product.LowestPrice en descending commande.

Ce que vous voulez est

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);

que vous pouvez obtenir à l'aide de la syntaxe de la requête par

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;

Pour les détails de la traduction de la syntaxe de la requête aux appels de méthode, voir la spécification du langage. Sérieusement. La lire.

18voto

J'ai une autre option dans cette situation. Ma liste est objList, et j'ai commander, mais les valeurs null doit être à la fin. ma décision:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));

12voto

user2919008 Points 21

ma décision:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)

7voto

AaronLS Points 12720

C'est ce que j'ai trouvé parce que je suis en utilisant des méthodes d'extension et mon élément est une chaîne, donc pas d' .HasValue:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)

Cela fonctionne avec LINQ 2 objets en mémoire. Je n'ai pas tester avec les objectifs EF ou toute DB ORM.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X