平时使用 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. SpringBoot处理日期转换问题

    前台传一个datetime类型的数据即yyyy-MM-dd HH:mm:ss格式的数据黑后台controller,结果发现接收到的对象为yyyy-MM-dd 00:00:00,处理这个问题可以在con ...

  2. [html]CSS中的margin、border、padding区别

    图解CSS padding.margin.border属性W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层. ...

  3. 微信小程序(一):编写58同城页面

    2018.3.25 这个时间我觉得更具58页面进行模仿. 微信小程序,标题更改在app.json文件中window属性. window用于设置小程序的状态栏.导航条.标题.窗口背景色.注意在app.j ...

  4. O365 Manager Plus帮助台委派功能一览表

    O365 Manager Plus帮助台委派介绍 虽然Office 365允许您在全球任何地方工作,但它提供的管理功能十分不足.当一个组织分布在多个国家/地区时,一个管理员很难单独管理所有用户和邮箱. ...

  5. 01 C语言程序设计--01 C语言基础--第1章 C语言概述&第2章 GCC和GDB

    走进嵌入式开发的世界,企业级项目课程让你达到企业嵌入式应用开发要求.名师在线答疑,解决疑难.科学评测体系,系统评估学习.核心项目实........ 30 门课程 241小时12分钟 824 人学习 学 ...

  6. 2019浙江省赛B zoj4101 Element Swapping(推公式)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6003 题意 \(数组a通过交换一对数字,得到了b数组,给出x=\sum^n_{ ...

  7. DataTransfer对象的一些总结

    所有元素都支持防止目标事件,但是这些元素默认是不允许释放的,如果拖动元素经过不允许放置的元素无论用户如何操作,都不会触发drop事件,不过可以把任何元素变成有效的放置目标.方法是重写dropenter ...

  8. MySQL数据库(一)

    一:MySQL的简单介绍 MySQL属于关系型数据库,数据是以行和列的形式去存储(表),表中的每一行叫一条记录,表中的每一列叫一个字段,表和表之间的逻辑关联叫关系. 二:MySQL的基本操作 (一)M ...

  9. You just run!

    第一篇博客,无关技术,有关身体. 写一篇跑步干货 装备篇 用过的鞋: 光脚,拖鞋,人字拖,回力板鞋,皮鞋,特步,鸿星尔克,李宁超轻13,ASICS  gt2000,阿迪低端. 1,非常推荐攒钱买一双a ...

  10. 01 of lenrning python

    我也打算开始写博客啦!记录一下自己的学习过程~ 01密文登陆 这个在vscode中不显示密文 在cmd中看不到密码 # -*- coding: utf-8 -*- import getpass nam ...