使用Expression Tree构建动态LINQ查询

时间:2023-02-16 20:58:38

这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法。这个在很多系统开发过程中是非常有用的。

我这里给的一个解决方案是采用Expression Tree来构建。

其实这个技术很早就有,在.NET Framework 3.5开始引入。之前也有不少同学写过很多不错的理论性文章。我自己当年学习这个,觉得最好的几篇文章是由"装配脑袋"同学写的。【有时间请仔细阅读这些入门指南,做点练习基本就能理解】

Expression Tree上手指南 (一) - 装配脑袋 - 博客园

Expression Tree 上手指南 (二) - 装配脑袋 - 博客园

Expression Tree 上手指南 (三) - 装配脑袋 - 博客园

 

我下面给出的这个实例,希望能帮助大家更加深入理解这个技术,并且结合常见的LINQ to SQL来实现动态的查询。

下面这个查询,大家应该都很眼熟

使用Expression Tree构建动态LINQ查询

如果我们的条件是固定的,例如上例中,一共有两个条件,而且条件的逻辑判断也都是确定的,那么上面这样写很容易就能得到我们的结果。

但,问题是,如果我们的条件不是固定的呢?如果你需要根据用户的选择,然后动态构造一个查询呢?

我看过很多人做的一些通用查询界面,为了应对用户希望自主选择条件的这个需求,他们的做法往往就是用"拼接查询字符串"的做法来实现。这种方法勉强能实现要求,但性能和可维护性方面都相当差。

如果你了解了Expression Tree,那么上面这个查询可以修改为下面这样:

使用Expression Tree构建动态LINQ查询

 

由此可见,掌握了这个技术的话,那么以后写动态查询应该会如虎添翼,至少多了一种很好的思路。

顺便说一下,这个技术和反射有点类似,属于比较底层的技术,掌握了将对大家的编程能力会有所提升。

值得一说的是,就算是我们第一种写法,内部的实现也是使用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. 用PredicateBuilder实现Linq动态拼接查询

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

  7. Expression表达式树动态查询

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

  8. &lbrack;转&rsqb;打造自己的LINQ Provider(上):Expression Tree揭秘

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

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

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

随机推荐

  1. 使用自己的CSS框架(转)

    [经典推介]CSS框架选择向导 不少CSS框架已经存在了一段时间,但大多数Web开发人员避免使用它们. 相反最有经验的开发者希望创建自己的CSS框架,提供个性化解决方案的优势,并减少对第三方的解决方案 ...

  2. 【转】iOS开发--一步步教你彻底学会『iOS应用间相互跳转』

    1. 应用间相互跳转简介 在iOS开发的过程中,我们经常会遇到需要从一个应用程序A跳转到另一个应用程序B的场景.这就需要我们掌握iOS应用程序之间的相互跳转知识. 下面来看看我们在开发过程中遇到的应用 ...

  3. nginx&plus;gunicorn

    wsgi接口,使用gunicorn作为server,想在外层加nginx. 配置了 proxy_pass   http://127.0.0.1:9008; 访问报301. 参考gunicorn 官网配 ...

  4. Bootstrap框架的要点--栅格系统

    不同的公司要求使用框架有所不同,而Bootstrap框架在工作中使用频次较高,其中栅格系统在这一框架中的地位不容小觑,下面我们开始聊聊它吧. 简单介绍: Bootstrap提供了一套响应式.移动设备优 ...

  5. Linux入门之常用命令(12)用户管理

    [用户管理] linux如何查看所有的用户和组信息的方法: 1.cat /etc/passwd: 2.cat /etc/group 1. useradd useradd 命令可以创建一个新的用户帐号, ...

  6. 3、js无缝滚动轮播

    另一个无缝滚动轮播,带暂停,由于js是异步,用C面向过程的思想开始会很怪异很怪异,因为当你定时器里面需要执行的函数时间比较长或是有一段延时时,异步的代码会完全不同,但习惯就好了. 这个代码有几个问题, ...

  7. C&num;运算符的简单使用测试

    在代码中看到的代码中|=,有点不太理解故重新学习了下位运算符. 位运算符在 c# 中的测试用例 [TestMethod] public void TestMethod1() { var a = fal ...

  8. Vscode调试C的多文件工程配置

    关于Vscode的C语言的单文件调试,可以参见VScode调试C语言的设置(win10,Linux),里面已经说明基本的配置和使用. 下面说明一下如何调试多个文件的工程,首先写一个简单的工程,其中工程 ...

  9. &lbrack;VUE ERROR&rsqb; Error in render&colon; &quot&semi;TypeError&colon; Cannot create property &&num;39&semi;header&&num;39&semi; on boolean &&num;39&semi;true&&num;39&semi;&quot&semi;

    项目基于ElemnetUi进行的开发,在引入第三方扩展库 vue-element-extends 之后使用它的表格组件报了这个错 解决方案: 1.  删除项目中的 node_modules 2. 删除 ...

  10. nginx1&period;14的安装

    编译安装nginx1.14.2 #拷贝指定文件到当前目录下[root@localhost ~]# find /usr/share -iname "*.jpg" -exec cp { ...