利用 DynamicLinq 实现简单的动态表达式构建查询
平时使用 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 实现简单的动态表达式构建查询的更多相关文章
- 利用SpEL 表达式实现简单的动态分表查询
这里的动态分表查询并不是动态构造sql语句,而是利用SpEL操作同一结构的不同张表. 也可以参考Spring Data Jpa中的章节http://docs.spring.io/spring-data ...
- 利用python实现简单词频统计、构建词云
1.利用jieba分词,排除停用词stopword之后,对文章中的词进行词频统计,并用matplotlib进行直方图展示 # coding: utf-8 import codecs import ma ...
- 超简单的集成表达式树查询组件,Sy.ExpressionBuilder 使用说明
Sy.ExpressionBuilder是一套依赖于表达式树上的集成的查询组件.设计的初衷没别的,就为了少写代码,让查询业务可以变得更加模式化.目前可以从nuget 获取到该组件. 来到查询,查询实体 ...
- ORM动态表达式树查询
前言 接口获取参数后,创建返回值模型的条件表达式作为参数,传入使用依赖注入实例化后的业务层. 业务层创建返回值模型的IQUERY后,再使用参数条件表达式.最后进行延迟查询. 代码实现 参数模型Demo ...
- EntityFramework动态多条件查询与Lambda表达式树
在常规的信息系统中, 我们有需要动态多条件查询的情况, 例如UI上有多个选择项可供用户选择多条件查询数据. 那么在.net平台Entity Framework下, 我们用Lambd ...
- 记录Linq中lambda动态表达式的使用方式
项目中有的时候我们会用到动态表达式的方式去查询数据,这里简单记录下个人的使用方式,方便使用↓ //构建参数表达式 ParameterExpression parameter = Expression. ...
- Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3
在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...
- [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- LINQ to SQL 运行时动态构建查询条件
在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语句更麻烦一些.本文介绍了3种运行时动态构建查询条件的方法.本文中的例子最终实现的都是同一个功能,从Nor ...
随机推荐
- 快速实现抖音的分享&登录(android)
快速实现抖音分享与第三方登录 准备工作 1.注册抖音的key到抖音开放平台,点击这里查看步骤: 2.集成ShareSDK到Mob官网文档页面查看即可,点击这里查看集成: 业务代码 分享要求: 视频: ...
- bind()方法
当点击鼠标时,隐藏或显示 p 元素: $("button").bind("click",function(){ $("p").slideTo ...
- 第二周工作总结——NWNU李泓毅
注:因作业未全部提交完毕,故评分细则和千帆图等评分事项推后 1.助教博客链接:https://www.cnblogs.com/lmcmha/ 2.本周点评作业: https://www.cnblogs ...
- VMware虚拟机Linux增加磁盘空间的扩容操作
转载自点击打开链接 用VMwareware虚拟机安装的Red Hat Enterprise Linux系统剩余空间不足,造成软件无法正常安装.如果重新装一遍系统就需要重新配置好开发环境和软件的安装配置 ...
- 初学者必看的文章:在VM12中安装 RedHat RHEL7.2 系统的详细步骤:看我如何操纵RHEL系统
一.开始安装 1)新建虚拟机 RHEL7.2 2)成功引导系统--开机出现此画面 Install Red Hat EnterpriseLinux 7.2 安装RHLE7.2 操作系统 Test th ...
- 使用tcpdump探测TCP/IP三次握手
读计算机应该就同说过TCP/IP三次握手,但是都没有去验证过,今天心血来潮,去验证了一下,于是乎写下了这篇博客,可能写的可能有问题,还请多多指教 包括我学习,还有从很多资料来看资料,第三次握手,应该会 ...
- 重装win10+ubuntu 双系统 UEFI启动模式
有较强的时效性!!先看一眼日期是否太古老! 任务 卸载双系统中的Ubuntu14,安装Ubuntu16 环境 操作系统: Win10 + Ubuntu14双系统 硬盘: 固态硬盘 + 机械硬盘,电脑的 ...
- xmlhttprequest readyState 属性的五种状态
关于readystate五个状态总结如下: readyState 状态 状态说明(0)未初始化此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备.值 ...
- POM文件详解(2)
1 项目构建 <!-- 构建项目需要的信息 --> <build> <!-- 子项目可以引用的默认插件信息.该插件配置项直到被引用时才会被解析或绑定到生命周期. ...
- 画线代码V1.0.0
画线代码: 最终效果图: 优点: 1.效果还行,计算量也不大(就一点2维直线一般式能有多少运算量). 缺点: 1.每条线怎么也是建模,可能会有点开销. 2.编辑起来很是麻烦. 代码部分: /***** ...