创建返回排序lambda表达式的Generic方法

时间:2017-12-23 19:48:09

标签: c# entity-framework linq lambda expression

我创建了一个返回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;
}

但它会导致&#34; double&#34;属于&#34; Product.Price&#34;

  

System.ArgumentException:&#39;表达类型&#39; System.Double&#39;不能用于返回类型&#39; System.Object&#39;

我无法找到问题所在......

2 个答案:

答案 0 :(得分:0)

您可以将您的方法重写为以下添加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");

答案 1 :(得分:0)

您可以添加对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