使用ExpressionVisitor进行lambadaExpression的动态拼接
现有如下实体
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
根据这个实体创建一个Iqueryable<User>对象queryList
List<User> dList = new List<User> {
new User{Id=,Name="zhansan" },
new User{Id=,Name="lisi" },
new User{Id=,Name="wangwu" },
new User{Id=,Name="zhaoliu" },
new User{Id=,Name="sunqi" },
};
dList的where方法需要一个Func<User, bool> whereFunc参数来进行数据过滤,但很多时候whereFunc是动态的,我的查询条件有时是u=>u.Id==1||u.Id==2,有时条件为u=>u.Id==1||u.Id==2&&u.Name=="lisi"
如此看来条件是不固定的并且属性组合方式多种多样,这样就迫切地需要一种方法可以动态地拼接表达式
如下两个表达式,将演示如何和为一个表达式
Expression<Func<User, bool>> ef = u => u.Id == || u.Id == ;
Expression<Func<User, bool>> ef2 = y => y.Name == "lisi";
首先创建类MyVisitor
public class MyVisitor : ExpressionVisitor
{
Dictionary<ParameterExpression, ParameterExpression> map;
public MyVisitor(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return map[node];
}
}
此类继承自ExpressionVisitor类,此类是expression表达式的工具类,可对expression表达式内部的成员进行替换
首先我自定义了构造函数传入一个字典对象。作用在后面解释
然后我重写了VisitorParameter方法,此方法的参数node即为要修改的expression的参数部分,你的expression有多少个参数就会顺序触发此方法并传入相应参数
准备工作到此就结束了,接下来是拼接过程
var pl = ef.Parameters;
var dic = ef.Parameters.Select((f, i) => new { f, f2 = ef2.Parameters[i] }).ToDictionary(p => p.f2, p => p.f);
MyVisitor myVisitor = new MyVisitor(dic);
var body = myVisitor.Visit(ef2.Body);
var finalBody = Expression.And(ef.Body, body);
var fu = Expression.Lambda<Func<User, bool>>(finalBody, pl).Compile();
var re= dList.Where(fu).ToList();
首先得到字典dic其key为ef2的参数列表,值为ef的参数列表
然后创建刚才自定义的MyVisitor类的对象,并传入字典dic
之后调用myVisitor的Visit方法传入ef2的Body部分,此时根据MyVisitor中对VisitParameter的重写可知
protected override Expression VisitParameter(ParameterExpression node)
{
return map[node];
}
在内部myVisitor对传入的ef2.Body的每一个参数查询字典,并返回值,此值即为ef的参数值,此处就将ef2的参数都替换为ef1的参数了
接下来就是两个表达式的拼接部分
var body = myVisitor.Visit(ef2.Body);
var finalBody = Expression.And(ef.Body, body);
var fu = Expression.Lambda<Func<User, bool>>(finalBody, pl).Compile();
将两个表达式的body部分用and连接,并且使用pl为参数(这很重要,前面做这么多就是为了把ef2的body部分的参数更换为ef的参数)
这样就得到了拼接后的func,传入where作为条件进行查询
var re= dList.Where(fu).ToList();
使用ExpressionVisitor进行lambadaExpression的动态拼接的更多相关文章
- Lambda表达式动态拼接(备忘)
EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句 分类: C# Lambda/Linq Entity Framework 2013-05-24 06:58 ...
- EF 拉姆达 动态拼接查询语句
EF 动态拼接查询语句 using System; using System.Collections.Generic; using System.IO; using System.Linq; usin ...
- 初识Mybatis框架,实现增删改查等操作(动态拼接和动态修改)
此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...
- mybatis 使用记录(二) 动态拼接查询条件
2016-12-16 阅读项目代码时,在项目的xml文件中发现如下写法: SELECT student_user_id FROM tbr_student_class WHERE 1=1 <if ...
- 动态拼接 sql的时候 里面 如果有变量的话 按上面的方式进行处理
set @Sql_Sql = N' select top 1 @m_zw=zw,@m_zh=temp from ket where zd=''ddd'' ' print @Sql_Sql EXEC s ...
- 分享动态拼接Expression表达式组件及原理
前言 LINQ大家都知道,用起来也还不错,但有一个问题,当你用Linq进行搜索的时候,你是这样写的 var query = from user in db.Set<User>() ...
- 表达式树动态拼接lambda
动态拼接lambda表达式树 前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dappe ...
- 动态拼接lambda表达式树
前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...
- vue获得当前页面URL动态拼接URL复制邀请链接方法
vue获得当前页面URL动态拼接URL复制邀请链接方法 当前页面完整url可以用 location.href路由路径可以用 this.$route.path路由路径参数 this.$route.par ...
随机推荐
- [leetcode-500-Keyboard Row]
Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...
- java的logcat的简单使用
android.util.Log常用的方法有以下5个:Log.v() Log.d() Log.i() Log.w() 以及 Log.e() .根据首字母对应VERBOSE,DEBUG,INFO, WA ...
- Spring MVC 项目搭建 -5- spring security 使用数据库进行验证
Spring MVC 项目搭建 -5- spring security 使用数据库进行验证 1.创建数据表格(这里使用的是mysql) CREATE TABLE security_role ( id ...
- MySQL(一)--基本语法与常用语句
将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合称为数据库(Database,DB). 将姓名.住址.电话号码.邮箱地址.爱好和家庭构成等数据保存到数据库中,就可以随时迅速获取想要的 ...
- Vijos 1002 过河 状态压缩DP
描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上 ...
- 不用EF框架,完成完美实体映射,且便于维护!(AutoMapper,petapoco)
最近,需要搭建一个新项目,在需求分析时确定数据库中需要创建多个存储过程.所以如果还是用原来EF框架生成ADO.net实体模型的话,不利于修改. 主要是解决以下两个问题: 1.比如前端需要一个值,如果存 ...
- 容器_JDK源码分析_自己简单实现ArrayList容器
这几天仔细研究下关于ArrayList容器的jdk源码,感觉收获颇多,以前自己只知道用它,但它里面具体是怎样实现的就完全不清楚了.于是自己尝试模拟写下java的ArrayList容器,简单了实现的Ar ...
- pgsql 递归查询 分页
--向下查询 WITH RECURSIVE res AS ( union ALL SELECT t_tree.* FROM t_tree, res WHERE t_tree.pid = res.id ...
- spring boot 事件发布与接收
1.创建发布对象 LoginEvent 2.在要发布对象的地方注入 ApplicationEventPublisher @Autowired ApplicationEventPublisher pub ...
- 全网首创ISE入门级教程
转眼间我已经大三了,现在成为了实验室的负责人,对于下一届学生的纳新重任就交到了我的手上,想采取不同的方法暑假尽可能对他们进行一些培训,所以制作了此教程,说实话,在网上还没有找到关于ISE的入门级使用教 ...