使用 Entity Framework 和 Linq 进行动态排序

2024-01-20

我有另一个类似的问题在这里得到了回答,关于 NULL 值是订单的最后一个。

在 Dynamic Linq Order By 上将 NULL 行保留在最后 https://stackoverflow.com/questions/42277259/keep-null-rows-last-on-dynamic-linq-order-by

我还想看看是否可以使用具有以下条件的日期列执行相同的操作。

  1. 所有结束日期均位于当前日期且位于顶部的所有项目,按最近即将发生的事件排序
  2. 接下来是使用结束日期的所有过去事件,并与当前日期与过去的最近结束日期进行比较。我现在在纯 SQL 中做了类似的事情。

            (CASE 
                WHEN ev.EndDate >= GETDATE() THEN 1
                ELSE 2
            END) ASC,
            (CASE
                WHEN ev.EndDate >= GETDATE() THEN ev.EndDate
                ELSE ev.StartDate
            END) ASC,
    

示例:当前日期 2017 年 3 月 24 日

EndDate

2017年3月25日

2017 年 4 月 15 日

2017年7月29日

2017年3月23日

2016年2月22日

当前代码

public static class OrderByHelper
{
    public static IOrderedQueryable<T> ThenBy<T>(this IEnumerable<T> source, string orderBy)
    {
        return source.AsQueryable().ThenBy(orderBy);
    }

    public static IOrderedQueryable<T> ThenBy<T>(this IQueryable<T> source, string orderBy)
    {
        return OrderBy(source, orderBy, false);
    }

    public static IOrderedQueryable<T> OrderBy<T>(this IEnumerable<T> source, string orderBy)
    {
        return source.AsQueryable().OrderBy(orderBy);
    }

    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderBy)
    {
        return OrderBy(source, orderBy, true);
    }

    private static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> source, string orderBy, bool initial)
    {
        if (string.IsNullOrWhiteSpace(orderBy))
            orderBy = "ID DESC";
        var parameter = Expression.Parameter(typeof(T), "x");
        var expression = source.Expression;
        foreach (var item in ParseOrderBy(orderBy, initial))
        {
            var order = item.PropertyName.Split('.')
                .Aggregate((Expression)parameter, Expression.PropertyOrField);
            if (!order.Type.IsValueType || Nullable.GetUnderlyingType(order.Type) != null)
            {
                var preOrder = Expression.Condition(
                        Expression.Equal(order, Expression.Constant(null, order.Type)),
                        Expression.Constant(1), Expression.Constant(0));
                expression = CallOrderBy(expression, Expression.Lambda(preOrder, parameter), item.Direction, initial);
                initial = false;
            }
            expression = CallOrderBy(expression, Expression.Lambda(order, parameter), item.Direction, initial);
            initial = false;
        }
        return (IOrderedQueryable<T>)source.Provider.CreateQuery(expression);
    }

    private static Expression CallOrderBy(Expression source, LambdaExpression selector, SortDirection direction, bool initial)
    {
        return Expression.Call(
            typeof(Queryable), GetMethodName(direction, initial),
            new Type[] { selector.Parameters[0].Type, selector.Body.Type },
            source, Expression.Quote(selector));
    }

    private static string GetMethodName(SortDirection direction, bool initial)
    {
        return direction == SortDirection.Ascending ?
            (initial ? "OrderBy" : "ThenBy") :
            (initial ? "OrderByDescending" : "ThenByDescending");
    }

    private static IEnumerable<OrderByInfo> ParseOrderBy(string orderBy, bool initial)
    {
        if (String.IsNullOrEmpty(orderBy))
            yield break;

        string[] items = orderBy.Split(',');

        foreach (string item in items)
        {
            string[] pair = item.Trim().Split(' ');

            if (pair.Length > 2)
                throw new ArgumentException(String.Format("Invalid OrderBy string '{0}'. Order By Format: Property, Property2 ASC, Property2 DESC", item));

            string prop = pair[0].Trim();

            if (String.IsNullOrEmpty(prop))
                throw new ArgumentException("Invalid Property. Order By Format: Property, Property2 ASC, Property2 DESC");

            SortDirection dir = SortDirection.Ascending;

            if (pair.Length == 2)
                dir = ("desc".Equals(pair[1].Trim(), StringComparison.OrdinalIgnoreCase) ? SortDirection.Descending : SortDirection.Ascending);

            yield return new OrderByInfo() { PropertyName = prop, Direction = dir, Initial = initial };

            initial = false;
        }

    }

    private class OrderByInfo
    {
        public string PropertyName { get; set; }
        public SortDirection Direction { get; set; }
        public bool Initial { get; set; }
    }

    private enum SortDirection
    {
        Ascending = 0,
        Descending = 1
    }
}

据我了解,你有一个DateTime财产(俗称它Date),而不是常规排序

.OrderBy(x => x.Date)

有类似的东西

var baseDate = DateTime.Today;

您希望首先按升序对未来值进行排序,然后按降序对过去的值进行排序。

它可以通过以下通用方式实现(适用于 LINQ to Objects 以及 EF):

.OrderBy(x => x.Date >= baseDate ? x.Date : DateTime.MaxValue)
.ThenByDescending(x => x.Date >= baseDate ? DateTime.MinValue : x.Date)

要动态实现该功能,您可以在实现方法主体循环中插入以下内容:

if (order.Type == typeof(DateTime)) // && some other special condition
{
    var condition = Expression.GreaterThanOrEqual(
        order, Expression.Constant(DateTime.Today));
    var order1 = Expression.Condition(condition,
        order, Expression.Constant(DateTime.MaxValue));
    var order2 = Expression.Condition(condition,
        Expression.Constant(DateTime.MinValue), order);
    expression = CallOrderBy(expression,
        Expression.Lambda(order1, parameter), SortDirection.Ascending, initial);
    expression = CallOrderBy(expression,
        Expression.Lambda(order2, parameter), SortDirection.Descending, false);
    initial = false;
    continue;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Entity Framework 和 Linq 进行动态排序 的相关文章

随机推荐

  • C++11 中默认函数有什么意义?

    C 11 添加了告诉编译器的功能创建默认实现 http en wikipedia org wiki C 2B 2B0x Defaulting 2Fdeleting of standard functions on C 2B 2B objec
  • 如何在 Rails 中向数据库添加多列

    您好 我刚刚在 RoR 中创建了一个数据库 我现在想再添加 10 列 但是 我不想使用一次仅添加 1 列的以下类型的命令 rails generate migration AddClosing Hrs1ToBusinesses closin
  • ASP.NET奇怪的编译错误

    我不知道我的机器出了什么问题 但有一段时间我从 ASP NET 对于我的所有应用程序 收到以下奇怪的错误 Compilation Error Description An error occurred during the compilat
  • 通过匹配两列的值来过滤数据框

    我在 r 中有一个数据框 我想删除两列中字符串值相等的那些行 我在 r 中使用了 match 函数 但无法获得所需的输出 例如我的数据框是 ALDH1A1 ALDH1A1 ITGA7 CHRNA1 PPP1R9A ACTG1 SRGN SR
  • 无法安装漂亮

    我无法 pip install Prettytable 安装它的最佳选择是什么 sudo pip vvv install prettytable Downloading unpacking prettytable Getting page
  • 通过 Intent 发送 Arraylist

    我怎样才能收到定制ArrayList从另一个活动通过Intent 例如 我有这个ArrayList在活动A中 ArrayList
  • 捕获生成器内的错误并随后继续

    我有一个应该运行几天的迭代器 我希望捕获并报告错误 然后我希望迭代器继续 或者整个过程可以重新开始 这是函数 def get units self scraper units scraper get units i 0 while True
  • 正则表达式接受命令并分割命令、参数和参数值

    下午好 我认为我在这项特殊任务中有点超出了我的能力范围 我正在尝试创建一个正则表达式匹配函数来输入命令 并拆分命令名称 参数和参数值 新变量 Name Something Force 结果应该是 新变量 Name 某物 Force 到目前为
  • 从字符串中删除隐藏字符

    我的问题 我有一个通过电子邮件发送新闻通讯的 NET 应用程序 在 Outlook 中查看新闻通讯时 Outlook 会显示一个问号来代替它无法识别的隐藏字符 这些隐藏字符来自最终用户 他们将组成时事通讯的 html 复制并粘贴到表单中并提
  • 表单识别器无效模型状态[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我们通过以下步骤尝试了表单识别器自定义训练 API 2 0 https pnagarjuna wordpress com 2020
  • android:将Tab的单击颜色设置为TableRow的背景颜色

    我有一个选项卡布局 我有一个带有动态添加行的表格布局 当选择 单击 TableRow 时 我想将其背景颜色设置为选项卡的按下或单击颜色 我不想设置任何静态颜色 但想使用默认主题颜色 如何获取 Tablayout 的颜色信息 How to h
  • Delphi中如何检查两个事件是否指向同一个过程?

    假设我有一个链接到 Button1Click 过程的 Button1 OnClick 事件 我还有 Button2 OnClick 链接到其他一些程序 如何检查这两个事件是否从运行时链接到不同或相同的过程 我尝试测试是否 Button1 O
  • 与串口“Verifone VX520”通信

    我正在通过串口将数据发送到 Verifone VX520 支付设备 这是我第一次尝试与此类设备进行通信 SerialObj Open 字符串输入 02hPUR 10 99 000000000004 634 4761739001010010F
  • XSL 用插入符替换空格

    更新的代码
  • 根据用户在 ASP.net 中的设置定期发送邮件?

    在我的网络应用程序中 我想根据用户自己预先选择的时间段为用户发送邮件 例如 每 3 天向用户 01 发送 1 封 HTML 邮件 每 20 天向用户 02 发送 1 封 HTML 邮件我怎样才能做到这一点 有资源吗 我可以通过我的应用程序从
  • com.hazelcast.nio.serialization.HazelcastSerializationException

    我正在运行一个 OSGI 插件项目 没有捆绑包 我在其中集成了 hazelcast 我 当我尝试将数据添加为字符串和测试 bean 的映射时 它被添加到淡褐色投射映射中 但是 二 当我尝试获取地图时 它显示错误如下 com hazelcas
  • Chrome扩展如何在扩展目录中写入文件

    这只是一个关于 chrome 扩展文件写入的简单问题 是否可以在chrome扩展目录中写入文件 我的意思是在我拥有清单文件和其他脚本的同一文件夹中写入一个文件 到目前为止 我发现我可以通过 XMLHttpRequest 读取目录中的文件 但
  • 关键点描述符 OpenCV

    我试图了解如何获取给定的描述符KeyPoint在 OpenCV 中 到目前为止 我的代码如下所示 include
  • Android Studio 和 Ryzen CPU?

    我知道它可能会被标记为重复 但没有一个线程对我有帮助 所以我决定自己做一个 I m a Java后端开发人员我决定学习一些 Android 的东西 几年前我在 Android Studio 工作过i5 4570处理器 然后我放弃了 现在我发
  • 使用 Entity Framework 和 Linq 进行动态排序

    我有另一个类似的问题在这里得到了回答 关于 NULL 值是订单的最后一个 在 Dynamic Linq Order By 上将 NULL 行保留在最后 https stackoverflow com questions 42277259 k