LINQ order by null列,其中order是升序,nulls应该是last

我正在尝试按价格sorting产品清单。

结果集需要按列的LowestPrice按价格从低到高列出产品。 但是,这个列是可以空的。

我可以像这样按降序对列表进行sorting:

 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 

不过,我不知道如何按升序sorting。

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

尝试把两列按相同的顺序。

 orderby p.LowestPrice.HasValue descending, p.LowestPrice 

否则,每个orderby是对集合的单独操作,每次重新sorting。

这应该首先用一个值来sorting,然后是“值”的顺序。

这对理解LINQ查询语法以及如何将其转换为LINQ方法调用确实有帮助。

事实certificate

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

将被编译器翻译为

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

这强调不是你想要的。 按Product.LowestPrice.HasValuedescendingsorting,然后descending排列Product.LowestPrice.HasValue对整个集合进行重新sorting。

你想要的是

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

您可以使用查询语法来获取

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

有关从查询语法到方法调用的翻译的详细信息,请参阅语言规范。 认真。 阅读。

在这种情况下我有另一种select。 我的列表是objList,我必须sorting,但空值必须是最后的。 我的决定:

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

我的决定:

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

string值的解决scheme真的很奇怪:

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

唯一的原因是因为第一个expression式OrderBy()bool值进行sorting: true / falsefalse结果首先跟着true结果(可空),然后ThenBy()按字母顺序sorting非空值。

所以,我更喜欢做一些更具可读性的东西,例如:

 .OrderBy(f => f.SomeString ?? "z") 

如果SomeString为null,它将被replace为"z" ,然后按字母顺序sorting。

注意:这不是一个最终的解决scheme,因为"z"首先比z值更像zebra

更新 9/6/2016 – 关于@jornhd评论,这是一个很好的解决scheme,但它仍然有点复杂,所以我会build议把它包装在一个扩展类,如:

 public static class MyExtensions { public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector) { return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector); } } 

简单的使用它就像:

 var sortedList = list.NullableOrderBy(f => f.SomeString); 

这是我想到的,因为我使用扩展方法,也是我的项目是一个string,因此没有.HasValue

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

这与内存中的LINQ 2对象一起工作。 我没有用EF或任何DB ORM进行testing。

我试图find一个LINQ的解决scheme,但不能从这里的答案。

我的最后答案是:

 .OrderByDescending(p.LowestPrice.HasValue).ThenBy(p.LowestPrice)