使用Expression Tree构建动态LINQ查询
这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法。这个在很多系统开发过程中是非常有用的。
我这里给的一个解决方案是采用Expression Tree来构建。
其实这个技术很早就有,在.NET Framework 3.5开始引入。之前也有不少同学写过很多不错的理论性文章。我自己当年学习这个,觉得最好的几篇文章是由"装配脑袋"同学写的。【有时间请仔细阅读这些入门指南,做点练习基本就能理解】
Expression Tree上手指南 (一) - 装配脑袋 - 博客园
Expression Tree 上手指南 (二) - 装配脑袋 - 博客园
Expression Tree 上手指南 (三) - 装配脑袋 - 博客园
我下面给出的这个实例,希望能帮助大家更加深入理解这个技术,并且结合常见的LINQ to SQL来实现动态的查询。
下面这个查询,大家应该都很眼熟

如果我们的条件是固定的,例如上例中,一共有两个条件,而且条件的逻辑判断也都是确定的,那么上面这样写很容易就能得到我们的结果。
但,问题是,如果我们的条件不是固定的呢?如果你需要根据用户的选择,然后动态构造一个查询呢?
我看过很多人做的一些通用查询界面,为了应对用户希望自主选择条件的这个需求,他们的做法往往就是用"拼接查询字符串"的做法来实现。这种方法勉强能实现要求,但性能和可维护性方面都相当差。
如果你了解了Expression Tree,那么上面这个查询可以修改为下面这样:

由此可见,掌握了这个技术的话,那么以后写动态查询应该会如虎添翼,至少多了一种很好的思路。
顺便说一下,这个技术和反射有点类似,属于比较底层的技术,掌握了将对大家的编程能力会有所提升。
值得一说的是,就算是我们第一种写法,内部的实现也是使用Expression Tree来实现的,有兴趣的同学可以看看如下的IL代码。
IL_0001: ldarg.0
IL_0002: call
LINQPad.User.TypedDataContext.get_Employees
IL_0007: ldtoken
LINQPad.User.Employees
IL_000C: call
System.Type.GetTypeFromHandle
IL_0011: ldstr
"x"
IL_0016: call
System.Linq.Expressions.Expression.Parameter
IL_001B: stloc.1
// CS$0$0000
IL_001C: ldloc.1
// CS$0$0000
IL_001D: ldtoken
LINQPad.User.Employees.EmployeeID
IL_0022: call
System.Reflection.FieldInfo.GetFieldFromHandle
IL_0027: call
System.Linq.Expressions.Expression.Field
IL_002C: ldc.i4.5
IL_002D: box
System.Int32
IL_0032: ldtoken
System.Int32
IL_0037: call
System.Type.GetTypeFromHandle
IL_003C: call
System.Linq.Expressions.Expression.Constant
IL_0041: call
System.Linq.Expressions.Expression.GreaterThan
IL_0046: ldloc.1
// CS$0$0000
IL_0047: ldtoken
LINQPad.User.Employees.Title
IL_004C: call
System.Reflection.FieldInfo.GetFieldFromHandle
IL_0051: call
System.Linq.Expressions.Expression.Field
IL_0056: ldstr
"Sales Representative"
IL_005B: ldtoken
System.String
IL_0060: call
System.Type.GetTypeFromHandle
IL_0065: call
System.Linq.Expressions.Expression.Constant
IL_006A: ldc.i4.0
IL_006B: ldtoken
System.String.op_Equality
IL_0070: call
System.Reflection.MethodBase.GetMethodFromHandle
IL_0075: castclass
System.Reflection.MethodInfo
IL_007A: call
System.Linq.Expressions.Expression.Equal
IL_007F: call
System.Linq.Expressions.Expression.AndAlso
IL_0084: ldc.i4.1
IL_0085: newarr
System.Linq.Expressions.ParameterExpression
IL_008A: stloc.2
// CS$0$0001
IL_008B: ldloc.2
// CS$0$0001
IL_008C: ldc.i4.0
IL_008D: ldloc.1
// CS$0$0000
IL_008E: stelem.ref
IL_008F: ldloc.2
// CS$0$0001
IL_0090: call
System.Linq.Expressions.Expression.Lambda
IL_0095: call
System.Linq.Queryable.Where
IL_009A: stloc.0
// query
IL_009B: ldloc.0
// query
IL_009C: call
LINQPad.Extensions.Dump
使用Expression Tree构建动态LINQ查询的更多相关文章
- 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
-之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...
- dapper利用DynamicParameters构建动态参数查询
public static int GetTotalLogin(string username,DateTime start, DateTime end) { using (var _connecti ...
- [C#.NET 拾遗补漏]13:动态构建LINQ查询表达式
最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价.当天销售额.当月销售额等),再选择 小于或等于 和 大于或等于 ,再填写一个待比较的数值,对数据进行查询过滤. 如果 ...
- LINQ 学习路程 -- 查询操作 Expression Tree
表达式树就像是树形的数据结构,表达式树中的每一个节点都是表达式, 表达式树可以表示一个数学公式如:x<y.x.<.y都是一个表达式,并构成树形的数据结构 表达式树使lambda表达式的结构 ...
- 动态LINQ(Lambda表达式)构建
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...
- 【C#表达式树 开篇】 Expression Tree - 动态语言
.NET 3.5中新增的表达式树(Expression Tree)特性,第一次在.NET平台中引入了"逻辑即数据"的概念.也就是说,我们可以在代码里使用高级语言的形式编写一段逻辑, ...
- 用PredicateBuilder实现Linq动态拼接查询
在使用Linq查询的时候,特别是如果你在使用Entiry Framwork,有时会遇到动态查询的情况(客户的查询条件是不固定的拼接查询).我们能想到的第一方案应该是拼接SQL,的确这样是可以达到我们的 ...
- Expression表达式树动态查询
在进行数据列表的查询中,我们通常会使用两种方式进行查询: linq查询 数据库sql语句查询 这样固然可以实现查询,本人之前也都是这么做的,因为查询的条件很少.使用linq,可以将所有的查询条件的属性 ...
- [转]打造自己的LINQ Provider(上):Expression Tree揭秘
概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...
随机推荐
- Hyper-V初涉_Hyper-V虚拟机文件交换
使用虚拟机时,文件交互就显得十分重要.如果能实现物理机与虚拟机之间的文件交互,将会节省大量的时间.比较可惜的是,Hyper-V虚拟机并不支持USB存储设备,所以在文件交换上略显麻烦. 与Hyper-V ...
- iOS项目旋转控制
iOS6的旋屏控制技巧 在iOS5.1 和 之前的版本中, 我们通常利用 shouldAutorotateToInterfaceOrientation: 来单独控制某个UIViewController ...
- angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js
用angular有一段时间了,平日里只顾着写代码,没有注意到性能优化的问题,而今有时间,于是捋了捋,讲学习过程记录于此: 问题描述:由于采用angular做了网页的单页面应用,需要一次性在主布局中将所 ...
- 定时自动关闭messagebox
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- PPC MPC85xx e500学习笔记
powerpc的内存体系结构 E500内核中包含内存管理单元MMU,其包含两个查找表(TLB0 Transaction Lookside Buffer)和TLB1来实现虚拟地址和物理地址的转化,其中T ...
- linux-11 基本命令之 -工作期目录切换命令-pwd,cd,
pwd 命令用于显示当前的工作目录,格式为:pwd[选项] @1.查看当前的工作路径: [root@localhost /]# pwd cd 命令用于切换工作路径 格式为:"cd 目录名称& ...
- maven配置阿里云镜像
编辑%maven_home%/conf/settings.xml文件,添加 <mirror> <id>aliyun-maven</id> <mirrorOf& ...
- Async and Await 异步和等待
[第一次这么耐下性子认真写博客,虽然觉得很认真了,当毕竟是第一次嘛,以后再看肯定觉得很不咋滴的,更何况园子里有那么多的高人和大侠,这篇文章就权当练练手了,熟悉一下用客户端发表博客了,也希望大家多多照顾 ...
- Android 开发必备知识:我和 Gradle 有个约会
腾讯Bugly特约作者:霍丙乾 0.讲个故事 0.1 Ant,我还真以为你是只蚂蚁 真正开始近距离接触编程其实是在2012年,年底的时候带我的大哥说,咱们这个 app 发布的时候手动构建耗时太久,研究 ...
- Demystifying ASP.NET MVC 5 Error Pages and Error Logging
出处:http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging Error pages and error ...