表达式树动态拼接lambda
动态拼接lambda表达式树
前言
最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据。由于dapperLambda按条件查询时是传入表达式树的参数,这样比如其中查询条件有一个是审核状态,另外五个是模糊查询,那这查询时的表达式树参数就要写两次,这样使得代码看起来有很多是重复的,而且如果查询条件多的情况下,在写那表达式树参数时也容易漏写或错写。所以我在想如果可以动态拼接这表达式树,那这代码就要精简很多了。
正文
也许我的上面文字描述让你不明觉里,那下面我就配以简单的代码来再说明一下这个问题:

1 Expression<Func<SysUser, bool>> exp1 = s => s.UserName.Contains("1") && s.Age > 10;
2 Expression<Func<SysUser, bool>> exp2 = s => s.UserName.Contains("1") && s.Age > 10 && s.IsEnable == 1;
3 using (var context = new DbContext().ConnectionString(connString))
4 {
5 var result1 = context.Select<SysUser>(exp1).QueryMany();
6 var result2 = context.Select<SysUser>(exp2).QueryMany();
7 }

上面代码两次查询,第一次查询结果result1的结果是用户名中包含1而且年龄大于10,而结果result2中就是在查询结果result1的条件上再加上帐号生效这一条件。所以我们看到exp1和exp2的表达式树绝大部分是相同的,在这个示例里看着这点重复代码似乎还是可以接受的,但是在真实环境下,重复的代码就不止这一点点了。因为exp2和exp1相比,exp2只是在exp1之上多加了一个条件,那我们有没有方法可以在exp1的基础上再加一个条件赋值给exp2呢?答案当然是可以的。
表达式扩展类:

1 public static class ExpressionExt
2 {
3 public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
4 {
5 return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
6 }
7 public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2)
8 {
9 return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters);
10 }
11 }

上面这代码是我们这文章的核心,我在这里顺便解释一下这个And扩展方法它是怎么做的,它这里先是使用Expression类中的静态方法AndAlso把expr1和expr2的主体拼接在一起,如果AndAlso方法返回的是BinaryExpression类型的结果,而dapperLambda的条件参数需要的是Lambda表达式树,所以这里我们需要通过Expression.Lambda方法来构造一个委托类型来创建一个Lambda表达树。
那现在我们通过上面的扩展方法,再来优化一下我们最初举的例子看下:

1 Expression<Func<SysUser, bool>> exp1 = s => s.UserName.Contains("1") && s.Age > 0;
2 Expression<Func<SysUser, bool>> exp2 =exp1.And( s => s.IsEnable == 1);
3 using (var context = new DbContext().ConnectionString(connString))
4 {
5 var result1 = context.Select<SysUser>(exp1).QueryMany();
6 var result2 = context.Select<SysUser>(exp2).QueryMany();
7 }

结束语
虽然这个扩展方法就只有几行代码,但是如果少了这几行代码,在我们的代码里可能就要上了几十行、几百行代码了。有时解决问题的关键就是那么一个不起眼的东西,但就是这么一个不起眼的东西就能帮我们解决一些大问题。
说到这,让我想起了一句话——每多学一点知识,就少写一行代码。
表达式树动态拼接lambda的更多相关文章
- 关于Expression表达式树的拼接
最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. ...
- 动态拼接lambda表达式树
前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...
- Expression表达式目录树动态拼接 反射获取泛型方法
class TestOne { public String[] arr = { "1", "2", "3" }; public class ...
- C#使用表达式树动态调用方法并实现99乘法表
我们在使用C#编程的时候,经常使用反射来动态调用方法,但有时候需要动态的生成方法,下面介绍使用表达式树的方式来自动生成方法,并调用. 首先需要说明什么是表达式,熟悉Linq的程序猿都用过类似于下面的代 ...
- [2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)
声明 本文对Lambda表达式的扩展,示例代码来源于网络. 场景描述 web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况.在手写sql的情况下,我们一般会根据传入的参数,针对 ...
- Expression表达式树动态查询
在进行数据列表的查询中,我们通常会使用两种方式进行查询: linq查询 数据库sql语句查询 这样固然可以实现查询,本人之前也都是这么做的,因为查询的条件很少.使用linq,可以将所有的查询条件的属性 ...
- 通过LINQ表达式树动态构建查询条件
第一种方法: public static class PredicateExtensions { public static Expression<Func<T, bool>> ...
- Lambda表达式动态拼接(备忘)
EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句 分类: C# Lambda/Linq Entity Framework 2013-05-24 06:58 ...
- 【转】EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句
传统的操作数据库方式,筛选数据需要用StringBuilder拼接一大堆的WHERE子句. 在Entity Framework中,代码稍有不慎就会造成巨大性能消耗,如: using(var db=ne ...
随机推荐
- 基于集合成工控机Ubuntu系统安装分区详解
基于集合成工控机Ubuntu系统安装分区详解 硬件描述:双核的CPU,128G的固态硬盘 软件描述:使用Ubuntu12.04系统,内核3.8.0-29版本,QT4.8.1版本 1.新建分区表 /de ...
- 使用ssh远程执行命令批量导出数据库到本地(转)
前天正在跟前端的同事调试功能.服务器开好,模拟的玩家登录好,就在倒计时.这时突然运营的同事跑过来说要统计几个服务器玩家的一些情况,也就是需要从几个服的数据库导出部分玩家的数据.好吧,我看了一下时间,1 ...
- HTML+CSS - 前端设计的小技巧(持续更新......)
2015年7月6日20:28:20 1.设置文字的居中,非控件内的. :text-alain:center 2.图片在ASP.NET中,可以直接拖放到界面,自动形成img控件. 3.CSS直接在全局样 ...
- node-inspector使用
nodejs.gulp调试工具node-inspector使用 俗话说欲善其功,必先利其器. 作为目前新型的Web Server开发栈倍受开发者关注的Nodejs来说,调试技术是学习开发的基石,所以对 ...
- 跨平台编程中的宏定义(__LINE__和__DATE__极其有用)
要用师兄的计算机算东西,无赖那上面是WINDOWS的系统,为了写出能够跨平台的代码,需要在代码中用到宏来选择编译.一种方法是自己在Makefile里面定义好该平台对应的宏.实际上,编译器基本上都会有一 ...
- Qt布局管理
原地址:http://blog.csdn.net/lastsoup/article/details/7028243 设计软件中各个部件的位置排列,有两种方法: 1.设置widget的在父窗体中的坐标和 ...
- FastReport的WCF托管到Windows服务的配置文件
官网上找到的,还没有来得及研究,有时间了再研究. <?xml version="1.0"?> <configuration> <appSettings ...
- Boost::thread库的使用
阅读对象 本文假设读者有几下Skills [1]在C++中至少使用过一种多线程开发库,有Mutex和Lock的概念. [2]熟悉C++开发,在开发工具中,能够编译.设置boost::thread库. ...
- Qt学习经验之quit()、exit()、close()《转载》
使用QT编辑界面,其中带来很大方便的一点就是Qt中自带丰富的.种类齐全的类及其功能函数,程序员可以在编辑程序的过程中简单地直接调用.关于窗口关闭的操作,在这里指出常用的三个槽,即quit(),e ...
- DELPHI 通過窗口句柄或窗口标题得到进程句柄
DELPHI 通過窗口句柄或窗口标题得到进程句柄2009年05月08日 星期五 10:15procedure TForm1.Button1Click(Sender: TObject);varhWind ...