[英]Using the Select method for dynamic queries and expression trees
I am attempting to create a dynamic query using expression trees to match the following statement: 我试图使用表达式树创建一个动态查询来匹配以下语句:
var items = data.Where(i => i.CoverageType == 2).Select(i => i.LimitSelected);
I can create the where method and get a result from it; 我可以创建where方法并从中获取结果; however, I cannot create the select method.
但是,我无法创建select方法。
Here is my where method: 这是我的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 }));
This is what I am using for the select method: 这是我用于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})
);
When I run the code I get this error: 当我运行代码时,我收到此错误:
No generic method 'Select' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments.
类型'System.Linq.Enumerable'上没有泛型方法'Select'与提供的类型参数和参数兼容。 No type arguments should be provided if the method is non-generic.
如果方法是非泛型的,则不应提供类型参数。
I have also tried changing Enumerable to Queryable and I get the same error. 我也尝试将Enumerable更改为Queryable,我得到了同样的错误。
No need to use Expression.Call, you can directly construct Expression Tree instead; 无需使用Expression.Call,您可以直接构造表达式树; I have create a static method which help me generate dynamic query:
我创建了一个静态方法来帮助我生成动态查询:
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 });
}
This might help with the error you describe above. 这可能有助于您在上面描述的错误。
You don't need to create your own where/select however, the ones built into c#/linq work just fine with your own classes: 你不需要创建自己的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;}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.