【问题标题】:LINQ: Sort records in ascending order with NULL values lastLINQ:最后使用 NULL 值按升序对记录进行排序
【发布时间】:2016-08-04 19:40:42
【问题描述】:

我想根据名为 DisplayOrder 的列按升序对记录进行排序。如果 DisplayOrder 为 null 或 0,那么这些记录应该排在最后。默认情况下,带有 0 或 null 的 DisplayOrder 显示为顶部记录。我想确保所有具有 NULL DisplayOrder 的记录都出现在具有非 NULL DisplayOrder 的记录之后,然后按 DisplayOrder 排序,这样可以确保所有具有 DisplayOrder 的记录都正确排序。

这就是我试图实现它的方法。

public DataResponse<EKGType> GetByPage(KendoGridPost kendo)
    {
        try
        {
            DataResponse<EKGType> response = new DataResponse<EKGType>(ResponseType.Failure);

            using (BusinessEntities context = new BusinessEntities())
            {


                IEnumerable<EKGTypes> items = context.EKGTypes
                                                     .ToList()
                                                     .Select(c => MapEntity(c))
                                                     .OrderBy(c => c.DisplayOrder.HasValue)
                                                     .ToList();

                response.Data = items.Skip(kendo.Skip).Take(kendo.PageSize).ToList();
                response.Count = items.Count();
                response.ResponseType = ResponseType.Success;
            }

            return response;
        }
        catch (Exception ex)
        {
            return HandleDataResponseException<EKGType>(ex);
        }
    }

这将首先返回具有 null/0 值的记录。我一直在寻找过去的一个小时,可以在 sql 中找到答案,但在 linq 中找不到。

【问题讨论】:

    标签: c# mysql linq sorting


    【解决方案1】:

    OrderBy() 方法允许您传入自定义比较器。比如:

    public class NullAndZeroLastComparer : IComparer<int?>
    {
        public int Compare(int? x, int? y)
        {
            int xValue = x.HasValue && x != 0 ? x.Value : int.MaxValue;
            int yValue = y.HasValue && y != 0 ? y.Value : int.MaxValue;
            return xValue.CompareTo(yValue);
        }
    }
    

    然后你会像这样使用它:

    IEnumerable<EKGTypes> items = context.EKGTypes
        .ToList()
        .Select(c => MapEntity(c))
        .OrderBy(c => c.DisplayOrder, new NullAndZeroLastComparer())
        .ToList();
    

    【讨论】:

    • 也喜欢那个答案,但我更喜欢将逻辑直接放入OrderBy,而不是为此创建一个全新的类。无论如何都要 +1
    【解决方案2】:

    您可以使用int.MaxValueNULL 的其他名称:

    IEnumerable<EKGTypes> items = context.EKGTypes
                                  .ToList()
                                  .Select(c => MapEntity(c))
                                  .OrderBy(c => 
                                      c.DisplayOrder.HasValue 
                                      ? (c.DisplayOrder == 0 ? (int.MaxValue - 1) : c.DisplayOrder) 
                                      : int.MaxValue)
                                  .ToList();
    

    因此,您有效地按DisplayOrder 排序,而带有DisplayOrder == null 的那些将被视为他们的DisplayOrderint.MaxValue,而带有DisplayOrder == 0 的那些将被视为他们的DisplayOrderint.MaxValue - 1。 因此,首先所有非 NULL 和非 0 将按它们的 DisplayOrder 排序,然后是具有 0 的那些,最后是 NULL 值。

    【讨论】:

    • 放入后?? int.MaxValue 我收到错误消息“运算符'??'不能应用于'bool'和'int'类型的操作数“
    • 您是否删除了.HasValue?只有c.DisplayOrder ?? int.MaxValue 没有HasValue
    • @RenéVogt 该解决方案适用于空值,但要求 0 也排在最后呢?
    • 抱歉,我忘记取下 .HasValue。就像你说的它适用于 NULL 值,但我需要最后显示 0 的值
    猜你喜欢
    • 1970-01-01
    • 2017-02-22
    • 2021-06-04
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 2012-04-22
    • 2013-05-30
    相关资源
    最近更新 更多