前言

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

正文

  也许我的上面文字描述让你不明觉里,那下面我就配以简单的代码来再说明一下这个问题:

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

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

  表达式扩展类:

 public static class ExpressionExt
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2)
{
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters);
}
}

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

  那现在我们通过上面的扩展方法,再来优化一下我们最初举的例子看下:

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

结束语

 虽然这个扩展方法就只有几行代码,但是如果少了这几行代码,在我们的代码里可能就要上了几十行、几百行代码了。有时解决问题的关键就是那么一个不起眼的东西,但就是这么一个不起眼的东西就能帮我们解决一些大问题。

  说到这,让我想起了一句话——每多学一点知识,就少写一行代码。

动态拼接lambda表达式树的更多相关文章

  1. Asp.net Core C#进行筛选、过滤、使用PredicateBuilder进行动态拼接lamdba表达式树并用作条件精准查询,模糊查询

    在asp.net core.asp.net 中做where条件过滤筛选的时候写的长而繁琐不利于维护,用PredicateBuilder进行筛选.过滤.LInq配合Ef.core进行动态拼接lamdba ...

  2. 表达式树动态拼接lambda

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

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

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

  4. EntityFramework动态多条件查询与Lambda表达式树

              在常规的信息系统中, 我们有需要动态多条件查询的情况, 例如UI上有多个选择项可供用户选择多条件查询数据. 那么在.net平台Entity Framework下, 我们用Lambd ...

  5. 分享动态拼接Expression表达式组件及原理

    前言 LINQ大家都知道,用起来也还不错,但有一个问题,当你用Linq进行搜索的时候,你是这样写的 var query = from user in db.Set<User>()      ...

  6. C# Lambda表达式详解,及Lambda表达式树的创建

    最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...

  7. 将简单的lambda表达式树转为对应的sqlwhere条件

    1.Lambda的介绍 园中已经有很多关于lambda的介绍了.简单来讲就是vs编译器给我带来的语法糖,本质来讲还是匿名函数.在开发中,lambda给我们带来了很多的简便.关于lambda的演变过程可 ...

  8. 动态创建Lambda表达式实现高级查询

    需求简介 最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表.其 中有一个功能是一个高级查询的需求,在查询条件方面大概有7.8个查询条件.需求就是如果一个条件 ...

  9. 动态组合lambda 表达式

    //记录实体集合—动态组合lambda 表达式 Expression<Func<AdEntity, bool>> thirdWhere = p => p.Observer ...

随机推荐

  1. 使用Boost.PropertyTree处理XML、JSON和INI数据

    Boost.PropertyTree 应该是 Boost 1.41.0 开始正式加入 Boost 版本的.目前 ( 2010/02/28 ) 能下到的最新版本是 1.42.0. 主要作用/应用场合 B ...

  2. 项目.c文件和.h文件关系

                "如有不正确之处,请指出,谢谢"       --Mood 对于一个项目,我们应该要很好的处理众多的.c和.h文件. 1.通过头文件调用库功能:#inclu ...

  3. Oracle_Database_11g_标准版_企业版__下载地址_详细列表

    Oracle_Database_11g_标准版_企业版__下载地址_详细列表 Oracle Database 11g Release 2 Standard Edition and Enterprise ...

  4. 如何删除JAVA集合中的元素

    经常我们要删除集合中的某些元素.有些可能会这么写. public void operate(List list){ for (Iterator it = list.iterator(); it.has ...

  5. 如何学习php之吐槽

    我也做了php一段时间了.从技术层面上解释吧.   深入学习任何的东西都要有个体系.   1 完整的学习整个体系结构.解决有什么的问题.   推荐看看这个.http://www.open-open.c ...

  6. Java描述语言、国家和地理的类——Locale

    Locale类代表一个特定的地理.语言和国家环境.一个Locale的实例对象本身不会验证它代表的语言和国家地区信息是否正确,只是向一些对国家和语言.地理等比较敏感的类提供国家地区语言信息,这些类有Da ...

  7. 后台调用外部程序的完美实现(使用CreateDesktop建立隐藏桌面)

    最近在做的一个软件,其中有一部分功能需要调用其它的软件来完成,而那个软件只有可执行文件,根本没有源代码,幸好,我要做的事不难,只需要在我的程序启动后,将那个软件打开,在需要的时候,对其中的一个文本矿设 ...

  8. 绑定运行计划sql_plan_baseline

    --因为生产环境运行的sql变化较快,版本号公布比較频繁,造成sql的运行计划不是非常稳定.常常会有一些性能非常查的sql出现 --对于这些sql,我们能够使用sql_plan_baseline对运行 ...

  9. linux公社的大了免费在线android资料

    2011年linux数据库的android在线分享 linux公社:开源公社             本文撰写:杨凯专属频道 2011年9月12日 21:39 <目录> Android 3 ...

  10. System.getProperty("catalina.home")

    System.getProperty("catalina.base"),服务器配置目录