声明

本文对Lambda表达式的扩展,示例代码来源于网络。

场景描述

web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况。在手写sql的情况下,我们一般会根据传入的参数,针对where部分进行sql语句的动态组装,而现在在使用EF的时候遇到这个问题,查询条件不再是以sql字符串的形式传递了,而是一个Lambda表达式,那么如何进行Lambda表达式的动态构造呢?

虽然Lambda表达式可以声明为变量,但是要进行表达式累加,目前并没有默认的、好用且方便的方法,参考了很多资料,寻到一剂良方。

先看看效果

先看看扩展后的使用示例:

  1. public ActionResult List(int? page, string where)
  2. {
  3. Expression<Func<ComArticle, bool>> Conditions = PredicateExtensions.True<ComArticle>();
  4. Conditions = Conditions.And(x => x.Shenhe == true && x.Company.City.CityId == CurrentCity.CityId);
  5. int t_id = 0;
  6. if (int.TryParse(where.GetByName("t"), out t_id) && t_id > 0 && t_id < 7)
  7. {
  8. var tmp = (EN_ArticleType)Enum.Parse(typeof(EN_ArticleType), t_id + "");
  9. Conditions = Conditions.And(x => x.Type == tmp);
  10. }
  11. var items = articleRepo.GetMany(Conditions).OrderByDescending(a => a.AddTime).ToPagedList(page ?? 1, 5);
  12. return View(items);
  13. }

如果有传入的t_id则Conditions会通过And条件累加Type筛选。

这里的关键在于对Expression的扩展,和PredicateExtensions.True()这个东西。

那么,我们看看PredicateExtensions的代码。

扩展

简单的扩展,受益于ExpressionVisitor。

  1. public class ParameterRebinder : ExpressionVisitor
  2. {
  3. private readonly Dictionary<ParameterExpression, ParameterExpression> map;
  4. public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
  5. {
  6. this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
  7. }
  8. public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
  9. {
  10. return new ParameterRebinder(map).Visit(exp);
  11. }
  12. protected override Expression VisitParameter(ParameterExpression p)
  13. {
  14. ParameterExpression replacement;
  15. if (map.TryGetValue(p, out replacement))
  16. {
  17. p = replacement;
  18. }
  19. return base.VisitParameter(p);
  20. }
  21. }
  22. public static class PredicateExtensions
  23. {
  24. public static Expression<Func<T, bool>> True<T>() { return f => true; }
  25. public static Expression<Func<T, bool>> False<T>() { return f => false; }
  26. public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
  27. {
  28. // build parameter map (from parameters of second to parameters of first)
  29. var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
  30. // replace parameters in the second lambda expression with parameters from the first
  31. var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
  32. // apply composition of lambda expression bodies to parameters from the first expression
  33. return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
  34. }
  35. public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  36. {
  37. return first.Compose(second, Expression.And);
  38. }
  39. public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
  40. {
  41. return first.Compose(second, Expression.Or);
  42. }
  43. }

ExpressionVisitor可以深入了解下。over

[2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)的更多相关文章

  1. Lambda 中如果构建一个查询条件,扔该Where返回我们需要的数据。

    有一个需求,比如所 省市县 这三个查询条件 都可能有可能没有,但是我们的查询条件怎么构建呢 首先需要看一下 Lambda中Where这个方法需要什么参数 public static IEnumerab ...

  2. Oracle的查询-条件表达式

    给emp表中员工起中文名 select e.ename from emp e; select e.ename, case e.ename when 'SMITH' then '曹贼' when 'AL ...

  3. Struts2的Action名称搜索顺序:2014.12.30

    struts.xml配置: <struts> <package name="hw" namespace="/test" extends=&qu ...

  4. 查询表格——建立动态表格,使用ajax输入查询条件将后台数据查询出来以表格的形式展示出来

    建立动态表格,使用ajax将前台查询条件传给后台,并将查询结果以表格的形式展示出来. 页面的展示效果如下图所示: 第一步:查询条件的部分: 代码如下: <div class="text ...

  5. shell(shell变量、条件表达式、流程控制)

    本章内容: 变量 运算 if语句 for语句 while语句 break.continue 实例 shell变量 1.shell变量简介 变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数 ...

  6. [Inside HotSpot] C1编译器优化:条件表达式消除

    1. 条件传送指令 日常编程中有很多根据某个条件对变量赋不同值这样的模式,比如: int cmov(int num) { int result = 10; if(num<10){ result ...

  7. python条件表达式:多项分支,双向分支

    # ### 多项分支 ''' if 条件表达式1: code1 code2 elif 条件表达式2: code3 code4 elif 条件表达式3: code5 code6 else: code7 ...

  8. if语句的嵌套以及条件运算符和条件表达式(初学者)

    1.当if语句中的执行语句又是if语句时,则构成了if语句的嵌套情形. 其一般形式可表示为: if() { if()……; } 或: if() if()语句1: else 语句2: else if() ...

  9. C#在泛型类中,通过表达式树构造lambda表达式

    场景 最近对爬虫的数据库架构做调整,需要将数据迁移到MongoDB上去,需要重新实现一个针对MongoDB的Dao泛型类,好吧,动手开工,当实现删除操作的时候问题来了. 我们的删除操作定义如下:voi ...

随机推荐

  1. maven-配置文件配置src/resource下的文件

    classpath*:只找到applicationContext.xml classpath:/找到了所有

  2. 配置LAMP实现WordPress

    环境说明: 在同一台主机上实现LAMP(Linux + Apache + MariaDB + PHP) CentOS 7.3.Apache 2.4.6.MariaDB 5.5.52.PHP 5.4.1 ...

  3. 13 年的 Bug 调试经验总结(来自蜗牛学院)

    在<Learning From Your Bugs>一文中,我写了关于我是如何追踪我所遇到的一些最有趣的bug. 最近,我回顾了我所有的194个条目,看看有什么经验教训是我可以学习的.下面 ...

  4. HDU1002——大整数加法

    题目: I have a very simple problem for you. Given two integers A and B, your job is to calculate the S ...

  5. Uva 548 二叉树的递归遍历lrj 白书p155

    直接上代码... (另外也可以在递归的时候统计最优解,不过程序稍微复杂一点) #include <iostream> #include <string> #include &l ...

  6. jquery.imagezoom.js制作鼠标悬停图片放大镜特效、参数和最简教程

    一.插件介绍 今天在用到放大镜效果的时候,突然发现网站里没有放大镜的插件.于是总结了一下,放到这里.为自己,也为他人提供方便.jquery.imagezoom.js这款插件用途很简单,就是鼠标移过去, ...

  7. Javascript闭包与作用域this

    闭包与this的一般用法 关于js函数与闭包的文章想必大家都是在熟悉不过的了,作为js核心亦即最强大的功能之一,每次回过头翻出来看一看,都会有不一样的收获与理解,经典的含义无非如此而已. 1.闭包 1 ...

  8. JavaScript中的数组Array方法

    push(),pop()方法 push(),pop()方法也叫栈方法,push()可以理解成,向末尾推入,而pop()恰好相反,可以理解成从末尾移除(取得). var nums=[1,2,3,4]; ...

  9. [STL] SET实用用法

    背景 今天考试深受平衡树之害,可以参见上一篇博客,想到了set却苦于实用的不熟练.同时QTY询问set的具体用法,所以写这篇博客,同时留作自用. 分类 参看了一下网上其他set博客,上来都是长篇大论概 ...

  10. jquery左右切换的无缝滚动轮播图

    1.HTML结构: <head> <script type="text/javascript" src="../jquery-1.8.3/jquery. ...