Using the Select Method for Dynamic Queries and Expression Trees

I am trying to create a dynamic query using expression trees to match the following expression:

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

I can create a where method and get the result from it; however, I cannot create a select method.

Here is my method:

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 }));

This is what I use for the select method:

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})

        );

When I run the code, I get this error:

There is no generic Select method in the type System.Linq.Enumerable compatible with the arguments and arguments of the supplied type. No type arguments should be provided unless the method is generic.

I also tried changing Enumerable to Queryable and I get the same error.

+5
source share
2 answers

Expression.Call, ; , :

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 });
}
+3

.

, /select, #/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;}
}
-1

All Articles