[2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)
声明
本文对Lambda表达式的扩展,示例代码来源于网络。
场景描述
web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况。在手写sql的情况下,我们一般会根据传入的参数,针对where部分进行sql语句的动态组装,而现在在使用EF的时候遇到这个问题,查询条件不再是以sql字符串的形式传递了,而是一个Lambda表达式,那么如何进行Lambda表达式的动态构造呢?
虽然Lambda表达式可以声明为变量,但是要进行表达式累加,目前并没有默认的、好用且方便的方法,参考了很多资料,寻到一剂良方。
先看看效果
先看看扩展后的使用示例:
public ActionResult List(int? page, string where)
{
Expression<Func<ComArticle, bool>> Conditions = PredicateExtensions.True<ComArticle>();
Conditions = Conditions.And(x => x.Shenhe == true && x.Company.City.CityId == CurrentCity.CityId);
int t_id = 0;
if (int.TryParse(where.GetByName("t"), out t_id) && t_id > 0 && t_id < 7)
{
var tmp = (EN_ArticleType)Enum.Parse(typeof(EN_ArticleType), t_id + "");
Conditions = Conditions.And(x => x.Type == tmp);
}
var items = articleRepo.GetMany(Conditions).OrderByDescending(a => a.AddTime).ToPagedList(page ?? 1, 5);
return View(items);
}
如果有传入的t_id则Conditions会通过And条件累加Type筛选。
这里的关键在于对Expression的扩展,和PredicateExtensions.True()这个东西。
那么,我们看看PredicateExtensions的代码。
扩展
简单的扩展,受益于ExpressionVisitor。
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
public static class PredicateExtensions
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// build parameter map (from parameters of second to parameters of first)
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with parameters from the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// apply composition of lambda expression bodies to parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.Or);
}
}
ExpressionVisitor可以深入了解下。over
[2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)的更多相关文章
- Lambda 中如果构建一个查询条件,扔该Where返回我们需要的数据。
有一个需求,比如所 省市县 这三个查询条件 都可能有可能没有,但是我们的查询条件怎么构建呢 首先需要看一下 Lambda中Where这个方法需要什么参数 public static IEnumerab ...
- Oracle的查询-条件表达式
给emp表中员工起中文名 select e.ename from emp e; select e.ename, case e.ename when 'SMITH' then '曹贼' when 'AL ...
- Struts2的Action名称搜索顺序:2014.12.30
struts.xml配置: <struts> <package name="hw" namespace="/test" extends=&qu ...
- 查询表格——建立动态表格,使用ajax输入查询条件将后台数据查询出来以表格的形式展示出来
建立动态表格,使用ajax将前台查询条件传给后台,并将查询结果以表格的形式展示出来. 页面的展示效果如下图所示: 第一步:查询条件的部分: 代码如下: <div class="text ...
- shell(shell变量、条件表达式、流程控制)
本章内容: 变量 运算 if语句 for语句 while语句 break.continue 实例 shell变量 1.shell变量简介 变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数 ...
- [Inside HotSpot] C1编译器优化:条件表达式消除
1. 条件传送指令 日常编程中有很多根据某个条件对变量赋不同值这样的模式,比如: int cmov(int num) { int result = 10; if(num<10){ result ...
- python条件表达式:多项分支,双向分支
# ### 多项分支 ''' if 条件表达式1: code1 code2 elif 条件表达式2: code3 code4 elif 条件表达式3: code5 code6 else: code7 ...
- if语句的嵌套以及条件运算符和条件表达式(初学者)
1.当if语句中的执行语句又是if语句时,则构成了if语句的嵌套情形. 其一般形式可表示为: if() { if()……; } 或: if() if()语句1: else 语句2: else if() ...
- C#在泛型类中,通过表达式树构造lambda表达式
场景 最近对爬虫的数据库架构做调整,需要将数据迁移到MongoDB上去,需要重新实现一个针对MongoDB的Dao泛型类,好吧,动手开工,当实现删除操作的时候问题来了. 我们的删除操作定义如下:voi ...
随机推荐
- html5 01 随记
一 HTML 是一种制作网站的标记语言 二.HTML基本语法 HTML 标签 html标签是html中的最基本单位 也是最重要的部分 通常使用尖角号 开始"<"和结束&qu ...
- Datatables快速入门开发--一款好用的JQuery表格插件
博主是一个java后端程序员小白,前端技术会用但不精通,做后台的一些功能经常要涉及表格的展示,分页,搜索,排序等等一系列功能,在经历了一段时间的原始手段,开始接触并使用Datatables,一个jqu ...
- TeamCity : Build 失败条件
允许用户配置 Build 失败的条件是很有用的功能,它是我们配置复杂 Build 流程的基础.TeamCity 为用户自定义 Build 失败条件提供了很好的支持.这些条件大体上可以分为两类,分别是: ...
- hdu--1018--Big Number(斯特林公式)
Big Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- Locust性能测试工具的安装及实际应用
一.安装Locust 安装Locust之前先安装的库:gevent库:第三方库,gevent为python提供了比较完善的协程支持.使用gevent,可以获得极高的并发性能. pip install ...
- <Mastering KVM Virtualization>:第二章 KVM内部原理
在本章中,我们将讨论libvirt.QEMU和KVM的重要数据结构和内部实现.然后,我们将深入了解KVM下vCPU的执行流程. 在这一章,我们将讨论: libvirt.QEMU和KVM的内部运作方式. ...
- theOS环境搭建
http://joeyio.com/ios/2014/01/01/make-a-mobile-substrate-tweak-using-theos/~/Doucment>: cd mytwea ...
- Luogu P2807 三角形计数
题目背景 三角形计数(triangle) 递推 题目描述 把大三角形的每条边n等分,将对应的等分点连接起来(连接线分别平行于三条边),这样一共会有多少三角形呢?编程来解决这个问题. 输入输出格式 输入 ...
- 实用css小技巧
display应用 在取消了ul/ol的默认样式{padding:0;list-style-type:none;}的时候:ul的li设置成了行内块(display:inline-block)的话,这时 ...
- 前端到后台ThinkPHP开发整站(3)
继续我的这个项目的第三晚的开发了,时间比较少,今晚写的代码不多,今晚仍然是造轮子写一个公共的控制器和一个公共的JS.直接上代码吧! 以下是一个公共的控制器,后台控制器都继承于它,构造函数中进行验证当前 ...