动态拼接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的更多相关文章

  1. 关于Expression表达式树的拼接

    最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. ...

  2. 动态拼接lambda表达式树

    前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...

  3. Expression表达式目录树动态拼接 反射获取泛型方法

    class TestOne { public String[] arr = { "1", "2", "3" }; public class ...

  4. C#使用表达式树动态调用方法并实现99乘法表

    我们在使用C#编程的时候,经常使用反射来动态调用方法,但有时候需要动态的生成方法,下面介绍使用表达式树的方式来自动生成方法,并调用. 首先需要说明什么是表达式,熟悉Linq的程序猿都用过类似于下面的代 ...

  5. [2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)

    声明 本文对Lambda表达式的扩展,示例代码来源于网络. 场景描述 web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况.在手写sql的情况下,我们一般会根据传入的参数,针对 ...

  6. Expression表达式树动态查询

    在进行数据列表的查询中,我们通常会使用两种方式进行查询: linq查询 数据库sql语句查询 这样固然可以实现查询,本人之前也都是这么做的,因为查询的条件很少.使用linq,可以将所有的查询条件的属性 ...

  7. 通过LINQ表达式树动态构建查询条件

    第一种方法: public static class PredicateExtensions { public static Expression<Func<T, bool>> ...

  8. Lambda表达式动态拼接(备忘)

    EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句 分类: C# Lambda/Linq Entity Framework 2013-05-24 06:58 ...

  9. 【转】EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句

    传统的操作数据库方式,筛选数据需要用StringBuilder拼接一大堆的WHERE子句. 在Entity Framework中,代码稍有不慎就会造成巨大性能消耗,如: using(var db=ne ...

随机推荐

  1. 网站遭遇DDOS简易处理

    网站遭遇DDOS攻击 netstat -an | grep ESTABLISHED 我们看到有大量的链接存在着,并且都是ESTABLISHED状态 for i in `netstat -an | gr ...

  2. 初入Android--环境搭建

    Android SDK 可以下载adt-bundle:包含了装好插件的eclipse和android sdk.下载好后,首先设置ANDROID_HOME环境变量:ANDROID_HOME=/home/ ...

  3. (转载)QT中PRO文件写法的详细介绍,很有用,很重要!

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在QT中,有一个工具qmake可以生成一个makefile文件,它是由.pro文件生成而来的,.pro文件的写法如下: 1. 注释从“#”开始,到 ...

  4. QT对话框中show和exec的区别

    转自:http://hi.baidu.com/wangjuns8/blog/item/24b382460dd1c1338694737d.html QDialog的显示有两个函数show()和exec( ...

  5. 数据层交换和高性能并发处理(开源ETL大数据治理工具--KETTLE使用及二次开发 )

    ETL是什么?为什么要使用ETL?KETTLE是什么?为什么要学KETTLE?        ETL是数据的抽取清洗转换加载的过程,是数据进入数据仓库进行大数据分析的载入过程,目前流行的数据进入仓库的 ...

  6. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

  7. poj 1018 Communication System 枚举 VS 贪心

    Communication System Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21631   Accepted:  ...

  8. Ubuntu下装QQ2012,让linux小白们不怕脱离windows

    嘿嘿,很多人可能跟我一样,QQ上同学群里会通知一些事项,所以我们希望可以在linux下开QQ,但是QQ官网做的QQ For Linux, 实在是烂的不行 那么怎么在linux下装我们平时在window ...

  9. spring获取bean 实例

    ApplicationContext ctx = new ClassPathXmlApplication("applicationContext.xml"); DataSource ...

  10. 百度地图js版定位控件

    一 概述 百度地图在最新版已加入浏览器定位控件,个人认为应该是既高德地图更新了一个浏览器也能定位功能后,百度不甘落后自己简简单单,草草写了个这个功能的定位控件 GeolocationControl 这 ...