这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态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查询的更多相关文章

  1. 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式

    -之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...

  2. dapper利用DynamicParameters构建动态参数查询

    public static int GetTotalLogin(string username,DateTime start, DateTime end) { using (var _connecti ...

  3. [C#.NET 拾遗补漏]13:动态构建LINQ查询表达式

    最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价.当天销售额.当月销售额等),再选择 小于或等于 和 大于或等于 ,再填写一个待比较的数值,对数据进行查询过滤. 如果 ...

  4. LINQ 学习路程 -- 查询操作 Expression Tree

    表达式树就像是树形的数据结构,表达式树中的每一个节点都是表达式, 表达式树可以表示一个数学公式如:x<y.x.<.y都是一个表达式,并构成树形的数据结构 表达式树使lambda表达式的结构 ...

  5. 动态LINQ(Lambda表达式)构建

    using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...

  6. 【C#表达式树 开篇】 Expression Tree - 动态语言

    .NET 3.5中新增的表达式树(Expression Tree)特性,第一次在.NET平台中引入了"逻辑即数据"的概念.也就是说,我们可以在代码里使用高级语言的形式编写一段逻辑, ...

  7. 用PredicateBuilder实现Linq动态拼接查询

    在使用Linq查询的时候,特别是如果你在使用Entiry Framwork,有时会遇到动态查询的情况(客户的查询条件是不固定的拼接查询).我们能想到的第一方案应该是拼接SQL,的确这样是可以达到我们的 ...

  8. Expression表达式树动态查询

    在进行数据列表的查询中,我们通常会使用两种方式进行查询: linq查询 数据库sql语句查询 这样固然可以实现查询,本人之前也都是这么做的,因为查询的条件很少.使用linq,可以将所有的查询条件的属性 ...

  9. [转]打造自己的LINQ Provider(上):Expression Tree揭秘

    概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...

随机推荐

  1. 【转】VC中的字符串处理

    http://hi.baidu.com/nmn714/item/ab8d2a96d0f2d6f228164727 貌似不少人刚开始做windows程序时都会纠结在字符串处理上,所以我把关于字符串处理的 ...

  2. IOS 通过苹果开放API检测更新

    #define APPID @"1067207206" -(void)onCheckVersion { NSDictionary *infoDic = [[NSBundle mai ...

  3. Knockoutjs 实践入门 (3) 绑定数组

    <form id="form1" runat="server">        <div>            <!--text ...

  4. 批量修改vss工作目录

    vss作为源代码版本控制工具,可以针对不同的文件夹设置不同的本地工作目录,这样可以方便我们不同的个性化需求.但是往往实际情况是,我们设置了不同的工作目录,后来却发现导致引用混乱,每个人每次获取项目文件 ...

  5. ASP.NET 5 (vNext) 理解和概述

    概述 ASP.NET 5 (又称为vNext) 是自ASP.NET产生15年以来一次革命性的更新, 我们可以从以下几点来理解其概貌和意义: ASP.NET 5是开源的 ASP.NET 5开发的WebA ...

  6. DataTables 控件使用和心得 (1) - 入门

    什么是DataTables DataTables是一个基于HTML/CSS/JavaScript的前端列表组件. 基于JQuery 开源并且免费(除特殊支持服务) 主要特色: 高性能,响应式,功能完整 ...

  7. 给 admin 新建的 hdfs 文件的权限

    su hdfs hdfs dfs -chown -R admin /   org.apache.hadoop.security.AccessControlException: Permission d ...

  8. Chrome开发者工具不完全指南(六、插件篇)

    本篇是Chrome开发者工具的结尾篇,最后为大家介绍几款功能强大的插件.在chrome商店里面有很多插件,没事建议大家去逛逛.不过需要FQ,所以诸位请自备神器.一.皮肤插件 首先是大家期盼已久,翘首以 ...

  9. js操作Dom的一些方法简化

    众所周知JQ的选择符很强大,一些看起来很难实现的功能只要在$符号中传入简单的字符串就可以获取到各种层级关系的DOM,而却不用考虑浏览器的兼容性.但有时候在做小项目的时候并不需要引入JQ,而又不想频繁繁 ...

  10. question

    1.软件工程技术和软件应用技术用什么区别吗? 2.软件工程专业和计算机技术(不是计算机科学与技术)有什么区别吗? 3.