表达式树动态拼接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 ...
随机推荐
- 使用MDK将STM32的标准库编译成lib使用
1 .使用MDK将STM32的标准库编译成lib使用[图文] http://www.cnblogs.com/zyqgold/p/3189719.html
- Win7+花生壳6.0+tomcat打做自己的web服务器(搭建自己的网站)(参考)
链接地址:http://blog.csdn.net/zhu_9527/article/details/23344623?utm_source=tuicool&utm_medium=referr ...
- 利用Winscp,Putty实现Windows下编写Linux程序
本文讲的方案实现以下功能:利用winscp和putty的脚本功能,实现在Window平台上编写代码,上传到Linux进行编译,然后取编译结果.需要用到3个文件,分别如下: (1) synchroniz ...
- WCF技术剖析之六:为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效
原文:WCF技术剖析之六:为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效 本篇文章来源于几天前一个朋友向我咨询的问题.问题是这样的,他说他采用ASP.NET应用 ...
- C++断言assert
assert宏是在标准库中提供的.它在库文件<cassert>中声明,它能够在程序中測试逻辑表达式,假设指定的逻辑表达式是false,assert()就会终止程序,并显示诊断消息.关闭断言 ...
- Swift - 使用NSURLSession加载数据、下载、上传文件
NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的sharedSession()和dataTaskWithR ...
- No enclosing instance of type Hello is accessible
1.static 关键字 修饰的成员被所有对象共享(包括成员变量和方法). 修饰的成员优先于对象存在. 存储于方法区(共享数据区)的静态区中. 静态方法只能访问静态成员. 静态方法中不可以使用this ...
- XFdtd 7.3.2发布增强生物电磁学中的核磁共振功能
XFdtd 日前发布7.3.2版,该版本主要针对生物电磁学中的核磁共振(MR)进行了功能增强,另外,也对软件的用户体验和计算性能进行了部分更新. XFdtd 是基于时域有限差分(FDTD)方法的全波三 ...
- 1.0.2-学习Opencv与MFC混合编程之---为播放AVI视频添加滑动条
源代码地址:http://download.csdn.net/detail/nuptboyzhb/3961642 版本1.0.2新增内容 Ø 全局变量和函数的添加: 在CVMFCview.cpp文件 ...
- python web with bottle and session (beaker)
python web with bottle and session (beaker) http://icodesnip.com/snippet/python/python-web-with-bott ...