使用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 ...
随机推荐
- jdk1.6 webService 客户端代码生成和测试
参数:测试webService的地址:http://10.113.11.1:9090/enocpService/buildingEngService?wsdl 1,eclipse中新建一个项目, 2, ...
- 基本XML解析---编写
#import "ViewController.h" #import "DDXML.h" @interface ViewController () @end @ ...
- Salesforce + AngularJS + Bootstrap
也可以分成三步: 1. 添加css和js引用: <apex:stylesheet value="https://maxcdn.bootstrapcdn.com/bootstrap/3. ...
- WebView一般用法总结
下面是webview常规的用法: import android.annotation.SuppressLint;import android.app.Activity;import android.o ...
- [C#进阶系列]专题二:你知道Dictionary查找速度为什么快吗?
一.前言 在之前有一次面试中,被问到你了解Dictionary的内部实现机制吗?当时只是简单的了问答了:Dictionary的内部结构是哈希表,从而可以快速进行查找.但是对于更深一步了解就不清楚了.所 ...
- 【Bugly技术干货】那些年我们用过的显示性能指标
Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言: 注:Google 在自己文 ...
- ENode 1.0 - 框架的物理部署思路
开源地址:https://github.com/tangxuehua/enode 上一篇文章,介绍了enode框架的总体目标,以及如何实现高吞吐.低延迟.高可用.无单点问题的实现思路.本篇文章,我们再 ...
- 补充 作业八:团队项目——Alpha阶段项目总结 补充
游戏界面: 单一.无背景图片 加入了背景 游戏结束: 无变化 无变化 游戏记录 无 加入数据库:有数据记录! 游戏初始化: 无 加入多种模式 此次任务后的总结: 经过上一次的答辩,以及认真观看了其他组 ...
- 作业三(代码规范、代码复审、PSP)
1.代码规范: 我支持代码要有规范,理由如下. (1).艺术是一个很带有个人风格的学科,天马行空才能凸显出自己的价值.但不要忘了,会艺术的不是生下来就会艺术, 他也需要按照前辈的步骤一步一步的学习基础 ...
- 开源中国(oschina)的Git托管
一些废话 对于使用CVS/SVN出身的人来说,Git始终有点难上手(比如我),因为概念较多,一时理不清,尽管网上已经有很多教程,其实后来我发现,要掌握它的办法就是使用它,着手开始用它做源码管理,有问题 ...