【问题标题】:Create Generic method that returns sort lambda expression创建返回排序 lambda 表达式的通用方法
【发布时间】:2017-12-23 19:48:09
【问题描述】:

我创建了一个返回 lambda 语句的方法,以便在 OrderByOrderByDescending linq 方法中使用。

我想使用排序表达式的行是这样的:

var results = _dbSet.AsNoTracking()
                    .OrderByDescending(sort)
                    .ToList();
return results;

我想用这个方法设置“排序”参数:

public static Expression<Func<TEntity, object>> GetSortExpression<TEntity>(string propertyName)
{
        var item = Expression.Parameter(typeof(TEntity), "entity");
        var prop = Expression.Property(item, propertyName);
        var selector = Expression.Lambda<Func<TEntity, object>>(prop, item);

        return selector;
}

但是对于像“Product.Price”这样的“double”属性会抛出错误

System.ArgumentException: 'System.Double' 类型的表达式不能用于返回类型 'System.Object'

我找不到问题出在哪里.....

【问题讨论】:

  • 我很困惑为什么您要返回 Expression&lt;Func&lt;TEntity, object&gt;&gt; 而不是 IQueryably&lt;TEntity&gt;。我已经完成了几个具有排序/过滤功能的项目。只有一次我必须重写和创建自己的表达式树,那是一个非常复杂的组合过滤器。

标签: c# entity-framework linq lambda expression


【解决方案1】:

你可以重写你的方法如下添加TKey

public static Expression<Func<TEntity, TKey>> GetSortExpression<TEntity, TKey>(string propertyName)
{
        var item = Expression.Parameter(typeof(TEntity), "entity");
        var prop = Expression.Property(item, propertyName);
        var selector = Expression.Lambda<Func<TEntity, TKey>>(prop, item);

        return selector;
}

所以,你可以把它当作

_dbSet.AsNoTracking()
                    .OrderByDescending(GetSortExpression<Enitity, double>("Price"))
                    .ToList();

据我了解,您的意图并不能解决您想要的问题。可能您希望它是接受任何领域的通用方法。为了支持它,您需要做更复杂的工作。首先,您应该知道一个字段类型,并根据它为 Int、Double 等创建一组调用。

switch (<field type>) {

case <type is double>:
  return _dbSet.AsNoTracking()
                        .OrderByDescending(GetSortExpression<Enitity, double>(FieldName))
                        .ToList();

case <type is int>:
  return _dbSet.AsNoTracking()
                        .OrderByDescending(GetSortExpression<Enitity, int>(FieldName))
                        .ToList();

作为替代方案,您可以手动创建 SQL 查询并添加任何排序并将其执行为:

your_dbcontext.Database.SqlQuery<TEntity>("your query order by field");

【讨论】:

    【解决方案2】:

    您可以添加对Convert 的调用来处理任何类型(必要时装箱)。这不一定像知道类型那样有效...

    public static Expression<Func<TEntity, object>> GetSortExpression<TEntity>(string propertyName)
    {
            var item = Expression.Parameter(typeof(TEntity), "entity");
            var prop = Expression.Convert(Expression.Property(item, propertyName), typeof(object));
            var selector = Expression.Lambda<Func<TEntity, object>>(prop, item);
    
            return selector;
    }
    

    使用 LINQPad,您可以创建一个示例 Expression 变量,然后创建 Dump() 其内容,以查看编译器如何处理某些情况。

    例如,通过使用

    Expression<Func<double, object>> f = p => p;
    f.Dump();
    

    您将看到编译器将UnaryExpression Convert 插入到主体中以将double 转换为object

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2022-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      相关资源
      最近更新 更多