平时使用 LINQ 进行一些简单的条件拼接查询一般都会这样操作:

public class SearchInputDto
{
public string ConditionA { get; set; }
public int? ConditionB { get; set; }
public string ConditionC { get; set; }
}

这里有三个条件,是前端传入的搜索条件,然后我们来编写一个查询语句:

public Task Search(SearchInputDto input)
{
var queryResult = _db.Where(z=>(input.ConditionA == null || z.Name == input.ConditionA)
&& (input.ConditionB == null || z.Number == input.ConditionB)
&& (input.ConditionC == null || z.Address == input.ConditionC)); // 执行其他操作... return Task.FromResult(0);
}

因为我们前端传入的条件不是固定的,所以有可能会出现有的条件没有传入的情况,如果是 SQL 的动态拼接 SQL 就可以了,而 Linq 你肯定是没法动态拼接的,只有自己构建一个表达式树传入到 IQuerable<T>.Where(Expression<Func<T,bool>> expression) 里面进行查询。

纯手工构建表达式树也不是不可以,只是略微麻烦,而我们则可以借助 System.Linq.Dynamic.Core 来方便的实现动态查询语句拼接。

他的常规用法如下:

官方 WIKI 地址:https://github.com/StefH/System.Linq.Dynamic.Core/wiki/Dynamic-Expressions

var query = db.Customers
.Where("City == @0 and Orders.Count >= @1", "London", 10)
.OrderBy("CompanyName")
.Select("new(CompanyName as Name, Phone)");

既然是字符串那么就可以拼接,我们来做一下改造。

首先去 NuGet 当中搜索 System.Linq.Dynamic.Core 库,安装之后我们来重新编写之前的查询范例,首先我们来写一个构建器,用于构建我们的表达式树:

using Abp.Runtime.Caching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;
using System.Text; namespace Abp.Linq.Expressions
{
public class ExpressionBuilder<TEntity, TSearchDto>
{
// 其实这里也可以通过传入 params Expression<Func<TRelateEntity, object>>[] selectFields 来构建
public Expression<Func<TEntity, bool>> Build(string[] excludeFields, TSearchDto dto)
{
var parameters = GenerateParametersDictionary(excludeFields, dto); StringBuilder sb = new StringBuilder();
var fieldNames = parameters.Keys.ToList(); // 动态拼接
for (int i = 0; i < fieldNames.Count; i++)
{
sb.Append(fieldNames[i]).Append($" == @{i}").Append(" && ");
} var lambdaStr = sb.ToString();
lambdaStr = lambdaStr.Substring(0, lambdaStr.Length - " && ".Length); // 构建表达式
return DynamicExpressionParser.ParseLambda<TEntity, bool>(new ParsingConfig(), false, lambdaStr, parameters.Values.ToArray());
} // 构建参数/值键值对,如果参数值为 NULL 则不进行构建
private Dictionary<string, object> GenerateParametersDictionary(string[] excludeFields, TSearchDto dto)
{
var typeInfo = typeof(TSearchDto);
var properties = typeInfo.GetProperties();
var parameters = new Dictionary<string, object>(); foreach (var property in properties)
{
var propertyValue = property.GetValue(dto); if (propertyValue == null) continue;
if (excludeFields == null) continue;
if (excludeFields.Contains(property.Name)) continue;
if (parameters.ContainsKey(property.Name)) continue; parameters.Add(property.Name, propertyValue);
} return parameters;
}
}
}

用法很简单,用刚才的代码作为一个例子:

public Task Search(SearchInputDto input)
{
var builder = new ExpressionBuilder<EntityA,SearchInputDto>();
var queryResult = _db.Where(builder.Build(null,input)); // 执行其他操作... return Task.FromResult(0);
}

可以看到已经变得十分简洁,这里仅仅作为抛砖引玉,其实还有更多高级的用法,这里不再赘述。

利用 DynamicLinq 实现简单的动态表达式构建查询的更多相关文章

  1. 利用SpEL 表达式实现简单的动态分表查询

    这里的动态分表查询并不是动态构造sql语句,而是利用SpEL操作同一结构的不同张表. 也可以参考Spring Data Jpa中的章节http://docs.spring.io/spring-data ...

  2. 利用python实现简单词频统计、构建词云

    1.利用jieba分词,排除停用词stopword之后,对文章中的词进行词频统计,并用matplotlib进行直方图展示 # coding: utf-8 import codecs import ma ...

  3. 超简单的集成表达式树查询组件,Sy.ExpressionBuilder 使用说明

    Sy.ExpressionBuilder是一套依赖于表达式树上的集成的查询组件.设计的初衷没别的,就为了少写代码,让查询业务可以变得更加模式化.目前可以从nuget 获取到该组件. 来到查询,查询实体 ...

  4. ORM动态表达式树查询

    前言 接口获取参数后,创建返回值模型的条件表达式作为参数,传入使用依赖注入实例化后的业务层. 业务层创建返回值模型的IQUERY后,再使用参数条件表达式.最后进行延迟查询. 代码实现 参数模型Demo ...

  5. EntityFramework动态多条件查询与Lambda表达式树

              在常规的信息系统中, 我们有需要动态多条件查询的情况, 例如UI上有多个选择项可供用户选择多条件查询数据. 那么在.net平台Entity Framework下, 我们用Lambd ...

  6. 记录Linq中lambda动态表达式的使用方式

    项目中有的时候我们会用到动态表达式的方式去查询数据,这里简单记录下个人的使用方式,方便使用↓ //构建参数表达式 ParameterExpression parameter = Expression. ...

  7. Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3

    在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...

  8. [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. LINQ to SQL 运行时动态构建查询条件

    在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语句更麻烦一些.本文介绍了3种运行时动态构建查询条件的方法.本文中的例子最终实现的都是同一个功能,从Nor ...

随机推荐

  1. Finance财务软件(科目标签专题)

    为了满足不同业务需求,对凭证中增加一些扩展内容,我们采用自定义科目标签的形式. 怎样自定义标签? 1. 增加科目掩码 这里的代码需要与模板表中tagLabel对应 这里的名称中对应掩码值,为16位整型 ...

  2. 每天五分钟,玩转Docker。

    Docker技术在国内如火如荼的流行了起来,我当然也想要赶上这时髦的技术啦.下面,我将重新拾起一年多未用的Docker,继续我的云计算之路. Day 1  学习Docker,先从Docker的命令行工 ...

  3. oracle中的日期函数的使用

    TO_DATE格式(以时间:2007-11-02   13:45:25为例) Year:               yy two digits 两位年                显示值:07   ...

  4. 虹软人脸检测和识别C# - API

    using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D ...

  5. python Strip函数和Split函数的用法总结 (python2.0,但用法与3.0是差不多的)

    strip函数原型 声明:s为字符串,rm为要删除的字符序列. 只能删除开头或是结尾的字符或是字符串.不能删除中间的字符或是字符串. s.strip(rm)        删除s字符串中开头.结尾处, ...

  6. Linux---基础指令(一)

    https://www.linuxprobe.com/chapter-02.html  (Linux就要这么学) 一.执行查看帮助命令 date:date命令用于显示及设置系统的时间或日期,格式为“d ...

  7. 配置Tomcat时遇到的问题

    今天准备开始JavaWeb的学习,先配置tomcat,前期一切顺利,可当我打开startup.bat,访问localhost:8080时,却显示localhost 拒绝了我们的连接请求. 于是我开始在 ...

  8. 破解某普通话测试app会员

    设备要求 已root的Android手机 软件要求 反编译工具 jeb.APK改之理(APK IDE) hook工具 frida.xposed. 布局分析工具 Android Device Monit ...

  9. HDU 6346 整数规划 (最佳完美匹配)

    整数规划 Time Limit: 5500/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  10. PHP单一文件入口框架简析

    <?php /** * PHP单一文件框架设计简析 * 1.MVC架构实现 * 2.URL路由原理 */ //URL路由原理 /** * 路由作用 * 获取url中的c和a变量,执行c类对应的方 ...