[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 ...
随机推荐
- Java中的数值和集合
数组array和集合的区别: (1) 数值是大小固定的,同一数组只能存放一样的数据. (2) java集合可以存放不固定的一组数据 (3) 若程序事不知道究竟需要多少对象,需要在空间不足时自动扩增容量 ...
- ajax-javascript原生-初步入门01(整理)
-----------------------------------2017.07.21写----------------------------------------- 1.ajax的原名: a ...
- teamviewer试用期到期解决
1.命令行输入:%appdata%删除teamviewer文件夹2.命令行输入:regedit删除teamviewer文件夹3.卸载tv4.控制面板->设备管理器->网络适配器->f ...
- ++i,i++和i += 1的区别
++i,i++和i += 1的区别 单条语句:i++;.++i;和 i += 1;等价. int i = 0; ++i; // 或者i++;或者i += 1; cout << i < ...
- TP3.2写上下篇
笔记笔记笔记记笔记!! ************************************************************************** 要实现上一篇跟下一篇,需要 ...
- 从入门到放弃,.net构建博客系统(二):依赖注入
文章目录:<从入门到放弃,.net构建博客系统> 从入门到放弃,.net构建博客系统(一):系统构建 从入门到放弃,.net构建博客系统(二):依赖注入 上一篇中有讲到项目启动时会进行io ...
- python学习===实现定时发送,方法一
#比如每3秒打印一次helloworld:from threading import Timer def printHello(): print "Hello World" t = ...
- IntelliJ IDEA Windows下Spark开发环境部署
0x01 环境说明 本地 OS: windows 10 jdk: jdk1.8.0_121 scala: scala-2.11.11 IDE: IntelliJ IDEA ULTIMATE 2017. ...
- instanceof问题
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:resu ...
- vue如何封装自己需要的方法
因为现在vue的流行,vue的各种插件都出来了,我们公司也是使用vue做项目,我自己在做项目的时候自己去琢磨了其他的插件以及结合自己对vue和es2015的理解,自己找的了一种在vue中使用封装方法的 ...