当前位置: 首页 > news >正文

C#:基于 EF Core Expression 的高性能动态查询构建实战 —— 面向大数据量环境的查询优化方案(全是干货,建议收藏)

在业务系统中,数据查询往往涉及多个可选条件的动态组合,如何写出性能优良、易维护的动态过滤代码,是提升查询效率和代码质量的关键。本文通过一个完整示例,讲解如何用 Expression<Func<TEntity, bool>> 构建动态过滤器,避免全表扫描,实现业务需求。


1. 需求场景

假设我们有一个通用数据实体 TEntity,需要支持以下过滤条件:

  • 单一字符串条件:比如客户编码、状态码等(可选)

  • 多选列表条件:比如地区代码列表、类型列表等(可选)

  • 时间区间条件:比如起始时间、结束时间(可选)

  • 多重多选列表条件:另一个列表字段过滤(可选)

这些条件需要灵活组合,当参数为空时对应条件不生效,保证数据库能够走索引,不做无谓扫描。


2. 核心思路

  • 用表达式表达各个条件,空值参数时用 true 透传,避免过滤。

  • 利用 Contains 实现列表过滤,EF Core 会自动翻译为 SQL 的 IN 语法。

  • 组合所有条件为一个整体表达式,传入 EF Core 查询。


3. 完整代码示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;namespace DynamicFilterDemo
{// 通用实体示例,业务实体请根据实际定义public class TEntity{public string StringField { get; set; }public string ListField { get; set; }public DateTime DateField { get; set; }public string AnotherField { get; set; }}// 查询参数封装public class QueryParams{public string SingleValue { get; set; }public List<string> ListValues { get; set; } = new List<string>();public DateTime? StartDate { get; set; }public DateTime? EndDate { get; set; }public List<string> AnotherList { get; set; } = new List<string>();}public class Repository{private readonly DbContext _dbContext;public Repository(DbContext dbContext){_dbContext = dbContext;}// 构建动态过滤表达式public Expression<Func<TEntity, bool>> BuildFilter(QueryParams param){return e =>// 单值过滤:参数为空不过滤(string.IsNullOrWhiteSpace(param.SingleValue) || e.StringField == param.SingleValue) &&// 多选列表过滤:列表为空不过滤(param.ListValues == null || param.ListValues.Count == 0 || param.ListValues.Contains(e.ListField)) &&// 时间区间过滤(!param.StartDate.HasValue || e.DateField >= param.StartDate.Value) &&(!param.EndDate.HasValue || e.DateField <= param.EndDate.Value) &&// 另一个多选列表过滤(param.AnotherList == null || param.AnotherList.Count == 0 || param.AnotherList.Contains(e.AnotherField));}// 查询接口示范public async Task<List<TEntity>> QueryAsync(QueryParams param){var filter = BuildFilter(param);var query = _dbContext.Set<TEntity>().Where(filter);// 这里可根据需要添加分页、排序等逻辑return await query.ToListAsync();}}
}

4. 代码解析

4.1 BuildFilter 方法

  • 使用 Expression<Func<TEntity, bool>> 构建动态表达式。

  • 每个过滤条件写成 (参数为空 || 匹配条件),保证空参数时不过滤。

  • 列表过滤用 Contains,自动映射为 SQL IN,高效且易维护。

  • 时间区间判断用标准比较操作符,保证能利用索引。

4.2 QueryAsync 方法

  • 调用构建好的过滤表达式,传入 EF Core 的 Where

  • 通过 await 异步执行数据库查询。

  • 可扩展分页、排序、投影等业务需求。


5. 性能和维护建议

  • 数据库索引:请确保字段 StringFieldListFieldDateFieldAnotherField 都建立了合适的索引,尤其是时间字段。

  • 表达式重用:对于复杂业务,可将表达式拆成多个小段,用 PredicateBuilder 等工具拼接,提高代码复用。

  • 空参数检查:务必保证参数为空时不会产生无谓过滤,避免全表扫描。

  • 日志调试:开启 EF Core SQL 日志,检查生成 SQL 是否合理,有无全表扫描。


6. 总结

  • 通过 Expression<Func<TEntity, bool>> 动态拼接查询条件,是 EF Core 处理中复杂动态查询的最佳实践。

  • 利用短路判断、Contains 以及区间判断,保证代码简洁且能生成高性能 SQL。

  • 该方法适合绝大多数动态多条件查询,能有效避免全表扫描,提升业务查询性能。

http://www.dtcms.com/a/303611.html

相关文章:

  • barba.js单页面应用程序
  • 基于VHDL的神经网络加速器设计实战
  • C++算法实例精讲
  • MKS E28H 0.05-100 Torr 加热 (100°C) Baratron 电容压力计,带蚀刻传感器 手侧
  • C++入门自学Day2-- c++类与对象(初识2)
  • 一文理清 Linux 软件管理核心知识:从程序组成到包管理工具
  • C语言中的数据结构--栈和队列(2)
  • VMware Workstation Pro 详细安装步骤
  • 线程安全
  • C++常见的仿函数,预定义函数,functor,二元操作函数(对vector操作,加减乘除取余位运算等 )
  • 异步通讯组件MQ
  • HTML应用指南:利用GET请求获取全国小米之家门店位置信息
  • 基于深度学习的医学图像分析:使用3D CNN实现肿瘤检测
  • hot100——第九周
  • 在Linux上使用DuckCP实现从csv文件汇总数据到SQLite数据库的表
  • 数据开源 | “白虎”数据集首批开源,迈出百万数据征途第一步
  • Zynq SOC FPGA嵌入式裸机设计和开发教程自学笔记:硬件编程原理、基于SDK库函数编程、软件固化
  • 2.DRF 序列化器-Serializer
  • 第五章:进入Redis的Hash核心
  • 小架构step系列28:自定义校验注解
  • 【算法训练营Day17】二叉树part7
  • 【VASP】二维材料杨氏模量与泊松比的公式
  • OpenLayers 综合案例-信息窗体-弹窗
  • 打卡day5
  • C++面试5题--5day
  • C++中的“对象切片“:一场被截断的继承之痛
  • 【SpringMVC】MVC中Controller的配置 、RestFul的使用、页面重定向和转发
  • rhel9.1配置本地源并设置开机自动挂载(适用于物理光驱的场景)
  • c++ 基础
  • windows内核研究(异常-CPU异常记录)