求写一个表达式树方法

qq_25735401 2019-05-25 10:48:48
需求是动态字段不为空的查询
dbContext.table.where(e=>e.field.hasValue); 需要field是动态传入。
我自己摸索写了个方法,但是报错:没有为类型“System.Nullable`1[System.Int32]”和“System.Int32”定义二进制运算符 Equal。
因为字段定义为可空类型了。这个怎么解决
还有不知道表达式树怎么构造 不为空的方法, 所以我下面写的直接笨方法的表达式:等于1或者等于-1。因为数据库保存为1,-1,和NULL。
public IQueryable<T> ExpressionQueryByField<T>(string field) where T:class
{
IQueryable<T> tIQueryable = dbContext.Set<T>();
ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
Expression left = Expression.Property(parameter, typeof(T).GetProperty(field));
Expression right = Expression.Constant(1);
Expression filter = Expression.Equal(left, right);
Expression right2 = Expression.Constant(-1);
Expression filter2 = Expression.Equal(left, right2);
Expression filter3 = Expression.Or(filter, filter2);

Expression pred = Expression.Lambda(filter3, parameter);
Expression expr = Expression.Call(typeof(T), "Where", new Type[] { typeof(T) }, Expression.Constant(tIQueryable), pred);
IQueryable<T> query = tIQueryable.AsQueryable().Provider.CreateQuery<T>(expr);
return query;
}
...全文
105 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
stherix 2019-05-26
  • 打赏
  • 举报
回复
Nullable<>其实是个比较特殊的类型,我以前写序列化库的时候就遇到过不少问题 HasValue有时候没法调用 但是直接判断是不是为null就行了
ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
Expression property = Expression.Property(parameter, typeof(T).GetProperty(field));
Expression notEqual = Expression.NotEqual(property, Expression.Constant(null));
Expression pred = Expression.Lambda(notEqual, parameter);
qq_25735401 2019-05-26
  • 打赏
  • 举报
回复
引用 4 楼 stherix 的回复:
[quote=引用 2 楼 qq_25735401 的回复:] 哇塞,这么简单 不好意思了,我是业余编程 改完后报另一个错了: 类型“EF.Model.BaseBar”上没有方法“Where”。 这方法我也是网上抄的。麻烦大神能否给个完整方法和调用示例,我用的是efcore.
Where是个扩展方法,Enumerable下面的静态方法
Delegate GetWhere<T>(string field)
{
    Type ienum = typeof(IEnumerable<T>);
    ParameterExpression parameter = Expression.Parameter(typeof(IEnumerable<T>), "c");
    ParameterExpression linqParameter = Expression.Parameter(typeof(T), "x");
    Expression property = Expression.Property(linqParameter, typeof(T).GetProperty(field));
    Expression notequal = Expression.NotEqual(property, Expression.Constant(null));
    var methods = typeof(Enumerable).GetMethods().Where(x => x.Name == "Where").First();
    var methodWhere = methods.MakeGenericMethod(typeof(T));
    Expression Where = Expression.Call(methodWhere, parameter, Expression.Lambda(notequal, linqParameter));
    return Expression.Lambda(Where, parameter).Compile();
}
可以获取IEnumable<T>的Where(x=>x.field != null)方法 var d = GetWhere<Entity>("data"); d.DynamicInvoke( tIQueryable.AsQueryable() ); 可以获取data不为空的列表 你自己也可以改写一下适合你的用途[/quote] 谢谢大神
stherix 2019-05-26
  • 打赏
  • 举报
回复
引用 2 楼 qq_25735401 的回复:
哇塞,这么简单 不好意思了,我是业余编程 改完后报另一个错了: 类型“EF.Model.BaseBar”上没有方法“Where”。 这方法我也是网上抄的。麻烦大神能否给个完整方法和调用示例,我用的是efcore.
Where是个扩展方法,Enumerable下面的静态方法
Delegate GetWhere<T>(string field)
{
    Type ienum = typeof(IEnumerable<T>);
    ParameterExpression parameter = Expression.Parameter(typeof(IEnumerable<T>), "c");
    ParameterExpression linqParameter = Expression.Parameter(typeof(T), "x");
    Expression property = Expression.Property(linqParameter, typeof(T).GetProperty(field));
    Expression notequal = Expression.NotEqual(property, Expression.Constant(null));
    var methods = typeof(Enumerable).GetMethods().Where(x => x.Name == "Where").First();
    var methodWhere = methods.MakeGenericMethod(typeof(T));
    Expression Where = Expression.Call(methodWhere, parameter, Expression.Lambda(notequal, linqParameter));
    return Expression.Lambda(Where, parameter).Compile();
}
可以获取IEnumable<T>的Where(x=>x.field != null)方法 var d = GetWhere<Entity>("data"); d.DynamicInvoke( tIQueryable.AsQueryable() ); 可以获取data不为空的列表 你自己也可以改写一下适合你的用途
qq_25735401 2019-05-26
  • 打赏
  • 举报
回复
自己摸索了下写出来了,顺便学了个Func,不过还是谢谢大神。 public Expression<Func<T,bool>> LambdaExpressionQueryByField<T>(string field) { ParameterExpression parameter = Expression.Parameter(typeof(T), "e"); Expression property = Expression.Property(parameter, typeof(T).GetProperty(field)); Expression notEqual = Expression.NotEqual(property, Expression.Constant(null)); return Expression.Lambda<Func<T,bool>>(notEqual, parameter); }
qq_25735401 2019-05-26
  • 打赏
  • 举报
回复
引用 1 楼 stherix 的回复:
Nullable<>其实是个比较特殊的类型,我以前写序列化库的时候就遇到过不少问题 HasValue有时候没法调用 但是直接判断是不是为null就行了
ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
Expression property = Expression.Property(parameter, typeof(T).GetProperty(field));
Expression notEqual = Expression.NotEqual(property, Expression.Constant(null));
Expression pred = Expression.Lambda(notEqual, parameter);
哇塞,这么简单 不好意思了,我是业余编程 改完后报另一个错了: 类型“EF.Model.BaseBar”上没有方法“Where”。 这方法我也是网上抄的。麻烦大神能否给个完整方法和调用示例,我用的是efcore.

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧