Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ order by null列,其中顺序为升序,null应为最后一个_C#_Linq_Sorting - Fatal编程技术网

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()
,sort
bool
值:
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”(“无选择”)的虚拟用户应始终位于最上面
我们修改了表模式并添加了“SortIndex”列,该列定义了一些排序组。(我们留下了5个空白,以便稍后插入组)

现在,就查询而言,它应该是:

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保留在列表的开头。