【问题标题】:Using the Select method for dynamic queries and expression trees对动态查询和表达式树使用 Select 方法
【发布时间】:2013-01-22 09:47:47
【问题描述】:

我正在尝试使用表达式树创建动态查询以匹配以下语句:

var items = data.Where(i => i.CoverageType == 2).Select(i => i.LimitSelected);

我可以创建 where 方法并从中获取结果;但是,我无法创建 select 方法。

这是我的 where 方法:

var parm = Expression.Parameter(typeof(BaseClassData), "baseCoverage");

var queryData = data.AsQueryable();

var left = Expression.Property(parm, "CoverageType");
var right = Expression.Constant(2m);
var e1 = Expression.Equal(left, right);

var whereMethod = Expression.Call(
    typeof(Queryable), 
    "Where", 
    new Type[] { queryData.ElementType }, 
    queryData.Expression, 
    Expression.Lambda<Func<BaseClassData, bool>>(e1, new ParameterExpression[] { parm }));

这就是我使用的 select 方法:

var selectParm = Expression.Property(parm, "LimitSelected");
     var selectMethod = Expression.Call(
        typeof(Enumerable),
        "Select",
        new Type[]{typeof(BaseClassData), typeof(decimal)},
        whereMethod,
        Expression.Lambda<Func<BaseClassData, decimal>>(selectParm, new ParameterExpression[]{ parm})

        );

运行代码时出现此错误:

类型“System.Linq.Enumerable”上没有通用方法“Select”与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

我也尝试将 Enumerable 更改为 Queryable,但我得到了同样的错误。

【问题讨论】:

  • SelectWhere 采用两个通用参数。
  • 你的意思是在ParameterExpression数组中吗?我问是因为 were 语句在编码时可以正常工作。如果我只使用 where 方法创建查询,一切正常。当我尝试将 select 方法添加到表达式树时。
  • 我将 typeof(BaseClassData) 添加到 selectMethod 的类型数组中,它可以工作。
  • 如果您自己解决了,那么您应该添加一个答案并将其标记为解决方案。

标签: c# linq exception-handling expression-trees


【解决方案1】:

无需使用Expression.Call,直接构造Expression Tree即可;我创建了一个静态方法来帮助我生成动态查询:

public static void Test(string[] args) {
  using (var db = new DBContext()) {
    //query 1
    var query1 = db.PrizeTypes.Where(m => m.rewards == 1000).Select(t => t.name);

    //query 2 which equal to query 1
    Expression<Func<PrizeType, bool>> predicate1 = m => m.rewards == 1000;
    Expression<Func<PrizeType, string>> selector1 = t => t.name;
    var query2 = db.PrizeTypes.Where(predicate1).Select(selector1);
    Console.WriteLine(predicate1);
    Console.WriteLine(selector1);
    Console.WriteLine();

    //query 3 which equal to query 1 and 2
    Expression<Func<PrizeType, bool>> predicate2 = GetPredicateEqual<PrizeType>("rewards", (Int16)1000);
    Expression<Func<PrizeType, string>> selector2 = GetSelector<PrizeType, string>("name");
    var query3 = db.PrizeTypes.Where(predicate2).Select(selector2);
    Console.WriteLine(predicate2);
    Console.WriteLine(selector2);

    //as you can see, query 1 will equal query 2 equal query 3
  }
}

public static Expression<Func<TEntity, bool>> GetPredicateEqual<TEntity>(string fieldName, object fieldValue) where TEntity : class {
  ParameterExpression m = Expression.Parameter(typeof(TEntity), "t");
  var p = m.Type.GetProperty(fieldName);
  BinaryExpression body = Expression.Equal(
    Expression.Property(m, fieldName),
    Expression.Constant(fieldValue, p.PropertyType)
  );
  return Expression.Lambda<Func<TEntity, bool>>(body, m);
}

public static Expression<Func<T, TReturn>> GetSelector<T, TReturn>(string fieldName)
  where T : class
  where TReturn : class {
  var t = typeof(TReturn);
  ParameterExpression p = Expression.Parameter(typeof(T), "t");
  var body = Expression.Property(p, fieldName);
  return Expression.Lambda<Func<T, TReturn>>(body, new ParameterExpression[] { p });
}

【讨论】:

  • Cheeeeeers,maaaaate... 我希望我早点找到这个。会节省我很多时间。我刚刚将它复制给我的代码。塔!
【解决方案2】:

This might help with the error you describe above.

您不需要创建自己的 where/select,但是,c#/linq 内置的那些可以与您自己的类一起正常工作:

void Main()
{
    List<testdata> data = new List<testdata>();
    Directory.GetFiles(@"C:\").ToList().ForEach(x=>data.Add(new testdata(){file=x,returnable=1}));
    data.Where(x=>x.file.Contains("g")).Select(x=>x.file).Dump();
}

class testdata
{
    public string file {get; set;}
    public string returnable {get; set;}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2018-02-16
    • 1970-01-01
    相关资源
    最近更新 更多