【问题标题】:LINQ - Dynamic expression to OrderByLINQ - OrderBy 的动态表达式
【发布时间】:2012-05-03 00:14:19
【问题描述】:

我有一个小问题,我会尽量详细解释。

在我的系统上,我有一个使用 EF 4.1 的通用存储库。 一切都很好,但是在某些情况下我遇到了一个问题,我需要对一些查询进行动态 orderBy。

我通过参数收到一个“字符串”,它代表我的班级中的字段,以执行 orderBy(如“id”或“description”)

部分代码:

        public class SomeClass
        {
            public int id { get; set; }
            public string description { get; set; }
        }

        // First we define the parameter that we are going to use
        // in our OrderBy clause. This is the same as "(parameter =>"
        // in the example above.
        var param = Expression.Parameter(typeof(SomeClass), "parameter");

        // Now we'll make our lambda function that returns the
        // request.SortingName property by it's name.
        var expression = Expression.Lambda<Func<SomeClass, int>>(Expression.Property(param, request.SortingName), param);

好吧,如果 "request.SortingName" 类型为 "int" (id) ,则此代码有效,但如果我想通过 "string" (description) 或其他类型进行 orderBy,则此代码不起作用。

我将表达式改为使用“对象”:

        var expression = Expression.Lambda<Func<SomeClass, object>>(Expression.Property(param, request.SortingName), param);

但是当我运行代码时,编译器会抛出下一个异常: 'System.Int32' 类型的表达式不能用于返回类型 'System.Object'

如果属性是字符串类型,例外是 “System.String”类型的表达式不能用于返回类型“System.Object”

换句话说,代码不适用于“对象”类型。

任何人都知道我该如何解决这个问题?

感谢您的宝贵时间。

【问题讨论】:

  • 您不能对目标类型使用反射并根据您的名称查找属性并从中确定正确的类型吗?
  • Dynamic LINQ OrderBy 可能会有所帮助

标签: asp.net-mvc linq entity-framework


【解决方案1】:

以下是我如何使用 EF4 和我在标准开发库中创建的一些通用方法进行动态排序和分页。重要的是您用于为 SortBy 方法创建 Lambda 表达式的第二段代码。

public enum SqlOrderByDirecton
{
    ASC,
    DESC
}

 //Derive Lambda Expression from string

 string sortByKey = "BusinessId";
 string value = "DESC";

 var p = Expression.Parameter(typeof(T));

 this.SortBy = Expression.Lambda<Func<T, dynamic>>(Expression.TypeAs(Expression.Property(p, sortByKey), typeof(object)), p).Compile();

 this.SortOrder = (DevCore.SqlOrderByDirecton)Enum.Parse(typeof(DevCore.SqlOrderByDirecton), value, true);

public static List<T> SortAndPaginate<T>(IEnumerable<T> query,
                                             Func<T, object> sortBy,
                                             SqlOrderByDirecton sortOrder,
                                             int rowLimit,
                                             int startRecord,
                                             out int recordCount)
    {
        recordCount = query.Count();

        List<T> list = new List<T>();

        if (sortOrder == SqlOrderByDirecton.ASC)
        {
            list = query.OrderBy(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }
        else
        {
            list = query.OrderByDescending(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }

        return list;
    }

【讨论】:

  • 不错!我修改了我的代码: Expression.Lambda>(Expression.TypeAs(Expression.Property(param, request.SortingName), typeof(object)), param);然后我做 .Compile();在我的存储库上,它的工作很完美。但是...如果我不“编译”,则查询不起作用。你知道是什么解释吗?
  • @HolloW 我不能 100% 确定这是为什么 - 我最初从我提出的问题中得到代码,它有效,我没有再看它 - stackoverflow.com/questions/9756407/…跨度>
  • 它真的正确地映射到 SQL 的 ORDER BY 中吗? Skip/Take 怎么样?
  • @Konstantin 您必须检查 SQL Server Profiler 或其他一些 EF 工具中的查询 - 但我不明白为什么不... OrderBy() 是标准的 Linq to Entity 语法.关于 Skip/Take,SQL Server 如何执行此操作存在一些复杂性(至少在旧版本 2008/12 中?),但它们同样是 Linq to Entities 的推荐开箱即用解决方案。顺便说一句,我绝不是说这些是有效的——这取决于数据的数量和查询的频率——如果你需要快速照明,你需要考虑原生 SQL,或者我的首选是存储过程或视图
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 2017-10-22
相关资源
最近更新 更多