C# LINQ order by null列,其中顺序为升序,null应为最后一个
我正试图按价格对一系列产品进行分类 结果集需要在C# LINQ order by null列,其中顺序为升序,null应为最后一个,c#,linq,sorting,C#,Linq,Sorting,我正试图按价格对一系列产品进行分类 结果集需要在最低价格列中按从低到高的价格列出产品。但是,此列可以为空 我可以按降序排列列表,如下所示: var products = from p in _context.Products where p.ProductTypeId == 1 orderby p.LowestPrice.HasValue descending orderby p.LowestPrice descending select p; // returns:
最低价格
列中按从低到高的价格列出产品。但是,此列可以为空
我可以按降序排列列表,如下所示:
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
但是我不知道如何按升序排序
// i'd like: 100, 101, 102, null, null
尝试将两列放在同一orderby中
orderby p.LowestPrice.HasValue descending, p.LowestPrice
否则,每次对集合重新排序时,每个orderby都是集合上的一个单独操作
这应该先对具有值的查询进行排序,然后再对值的顺序进行排序。这确实有助于理解LINQ查询语法以及如何将其转换为LINQ方法调用 原来
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.HasValue
的降序排序,然后按Product.LowestPrice
的降序重新排序整个集合
你想要的是
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;
有关从查询语法到方法调用的转换的详细信息,请参阅语言规范。认真地阅读它。在这种情况下,我有另一种选择。 我的列表是objList,我必须排序,但最后必须是null。 我的决定:
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)
我的决定:
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)
这是我想到的,因为我使用扩展方法,而且我的项是字符串,因此没有
。HasValue
:
.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)
这适用于内存中的LINQ 2对象。我没有使用EF或任何DB ORM对其进行测试。我试图找到解决此问题的LINQ解决方案,但无法从这里的答案中得出答案 我最后的回答是:
.OrderByDescending(p => p.LowestPrice.HasValue).ThenBy(p => p.LowestPrice)
字符串值的解决方案非常奇怪:
.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)
唯一有效的原因是第一个表达式,OrderBy()
,sortbool
值:true
/false
false
result先执行true
result(可空值),然后执行ThenBy()
按字母顺序对非空值进行排序
e.g.: [null, "coconut", null, "apple", "strawberry"]
First sort: ["coconut", "apple", "strawberry", null, null]
Second sort: ["apple", "coconut", "strawberry", null, null]
因此,我更喜欢做一些更具可读性的事情,比如:
.OrderBy(f => f.SomeString ?? "z")
如果SomeString
为空,它将替换为“z”
,然后按字母顺序排序
e.g.: [null, "coconut", null, "apple", "strawberry"]
First sort: ["coconut", "apple", "strawberry", null, null]
Second sort: ["apple", "coconut", "strawberry", null, null]
注意:这不是一个最终的解决方案,因为“z”
比z值(如斑马
)先到达
更新9/6/2016-关于@jornhd comment,这确实是一个很好的解决方案,但仍然有点复杂,因此我建议将其包装在扩展类中,例如:
.OrderBy(f => f.SomeString ?? "z")
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);
}
}
下面是一个扩展方法,若要对keySelector的子属性进行排序,可以检查null
public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, object> parentKeySelector, Func<T, object> childKeySelector)
{
return list.OrderBy(v => parentKeySelector(v) != null ? 0 : 1).ThenBy(childKeySelector);
}
还有一种方法:
//Acsending
case "SUP_APPROVED_IND": qry =
qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
ThenBy(r => r.SUP_APPROVED_IND);
break;
//….
//Descending
case "SUP_APPROVED_IND": qry =
qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
ThenByDescending(r => r.SUP_APPROVED_IND);
break;
SUP\u APPROVED\u IND是Oracle数据库中的字符(1)。
请注意,r.SUP\u APPROVED\u IND.Trim()==null
在Oracle db中被视为Trim(SUP\u APPROVED\u IND)为null
有关详细信息,请参见此:另一个选项(对于我们的场景非常方便):
我们有一个用户表,存储ADName、LastName、FirstName
- 用户应按字母顺序排列
- 也没有First-/LastName的帐户(基于其ADName),但位于用户列表的末尾
- ID为“0”(“无选择”)的虚拟用户应始终位于最上面
SELECT * FROM User order by SortIndex, LastName, FirstName, AdName;
在方法表达式中:
db.User.OrderBy(u => u.SortIndex).ThenBy(u => u.LastName).ThenBy(u => u.FirstName).ThenBy(u => u.AdName).ToList();
这将产生预期的结果:
ID | ADName | First Name | LastName | SortIndex
0 No Selection null null | 0
5 AD\ama Amanda Whatever | 5
1 AD\jon Jon Doe | 5
4 AD\Accounting null null | 10
3 AD\Support null null | 10
orderby p.LowestPrice??Int.MaxValue
是一种简单的方法。@PostMan:是的,很简单,它得到了正确的结果,但是OrderByDescending,ThenBy
更清晰。@Jason,是的,我不知道orderby
的语法,并且在寻找它时被跟踪到:)常见错误,人们对Lamda语法也这么做-使用.OrderBy两次而不是.ThenBy.This对顶部有值、底部有空字段的字段进行排序,我使用了:OrderBy p.LowestPrice==null,p.LowestPrice升序
希望能帮助别人。@DaveShaw感谢你的提示-尤其是评论-非常整洁-喜欢+1或只是。。。不要编写LINQ查询语法:)很好的解释非此我认为这更可读,没有讨厌的常量:.OrderBy(f=>f.SomeString!=null?0:1)。然后by(f=>f.SomeString)这可以在需要使用其他值(如0)代替null的情况下工作。是的。只需将null替换为0。这是唯一对我有效的答案,其余的将null保留在列表的开头。