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

自动过滤:用 AutoFilterer 实现高性能动态查询

🚀 自动过滤:用 AutoFilterer 实现高性能动态查询


📚 目录

  • 🚀 自动过滤:用 AutoFilterer 实现高性能动态查询
    • 🧩 项目场景
    • 🌟 AutoFilterer 核心优势
    • 🎯 项目结构流程图
    • 🛠 快速集成
      • 1️⃣ 安装依赖
      • 2️⃣ 注册服务(Program.cs)
    • 🌱 初始化种子数据流程图
    • 3️⃣ 实体与过滤 DTO
    • 4️⃣ Controller 实现:请求 & 缓存流程图
    • 🌐 示例请求与响应
    • 🧪 单元测试示例(xUnit)
    • 📊 最佳实践小结


🧩 项目场景

在中大型 .NET Web API 项目中,数据查询过滤是高频且重复度极高的任务。传统方式下:

  • 每个字段都需写 Where 条件;
  • 多字段组合查询冗长、易错;
  • Swagger 接口测试缺乏一致性与自动生成文档;

因此,引入 AutoFilterer —— 一个属性驱动的 LINQ 表达式生成器,支持动态查询和 OpenAPI 自动展示,全面提升代码质量与开发效率。


🌟 AutoFilterer 核心优势

🧩 特性✨ 描述
属性驱动DTO 上声明过滤规则,自动生成表达式
无需手写摒弃手工 LINQ 代码
多条件支持字符串、区间、布尔、枚举、日期等
OpenAPI 3.0与 Swagger UI 无缝集成
高性能表达式缓存、延迟执行、支持 EF Core
支持分页内置 PaginationFilterBase

🎯 项目结构流程图

在这里插入图片描述


🛠 快速集成

1️⃣ 安装依赖

dotnet add package AutoFilterer.Extensions.Microsoft.DependencyInjection --version 3.1.0
dotnet add package AutoFilterer.Swagger --version 3.1.0
dotnet add package System.Linq.Dynamic.Core --version 1.6.5

2️⃣ 注册服务(Program.cs)

using AutoFilterer.Swagger;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;var builder = WebApplication.CreateBuilder(args);// 1. AutoFilterer + 表达式缓存
builder.Services.AddAutoFilterer(options =>
{options.EnableExpressionCache = true;
});// 2. Swagger 集成 AutoFilterer 参数
builder.Services.AddSwaggerGen(c =>
{c.UseAutoFiltererParameters();c.SwaggerDoc("v1", new() { Title = "Book API", Version = "v1" });
});// 3. EF Core:演示用 InMemory,生产可切换 SQL Server
builder.Services.AddDbContext<AppDbContext>(opt =>
{opt.UseInMemoryDatabase("BooksDb");// 生产示例:// opt.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
});// 4. MVC + 全局 camelCase JSON 命名
builder.Services.AddControllers().AddJsonOptions(opts =>{opts.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;});// 5. 内存缓存,用于结果缓存
builder.Services.AddMemoryCache();var app = builder.Build();// Seed 数据
using (var scope = app.Services.CreateScope())
{var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();DbSeeder.Seed(db);
}// 中间件
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.Run();

🌱 初始化种子数据流程图

false
true
应用启动
创建 Scope
解析 DbContext
db.Books.Any?
执行 AddRange(Books)
SaveChanges()
种子数据完成

3️⃣ 实体与过滤 DTO

public class Book
{public Guid Id { get; set; }public string Title { get; set; }public string Author { get; set; }public DateTime PublishedDate { get; set; }public int PageCount { get; set; }
}
using AutoFilterer.Attributes;
using AutoFilterer.Types;
using System.ComponentModel.DataAnnotations;public class BookFilter : PaginationFilterBase
{[ToLowerContainsComparison]public string? Title { get; set; }[ToLowerContainsComparison]public string? Author { get; set; }[CompareTo(nameof(Book.PublishedDate), FilterType.GreaterThanOrEqual)]public DateTime? FromDate { get; set; }[CompareTo(nameof(Book.PublishedDate), FilterType.LessThanOrEqual)]public DateTime? ToDate { get; set; }[CompareTo(nameof(Book.PageCount), FilterType.GreaterThan)]public int? MinPages { get; set; }/// <summary>/// 支持动态排序,格式示例:"PublishedDate desc"/// </summary>public string? SortBy { get; set; }[Range(1, 100)]public override int PageSize { get; set; } = 10;
}

4️⃣ Controller 实现:请求 & 缓存流程图

hit
miss
客户端请求
BooksController
检查缓存
返回缓存结果
应用 ApplyFilter
应用动态排序
执行 CountAsync()
执行 Skip/Take & ToListAsync()
缓存结果
返回结果
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{private readonly AppDbContext _db;private readonly ILogger<BooksController> _logger;private readonly IMemoryCache _cache;public BooksController(AppDbContext db,ILogger<BooksController> logger,IMemoryCache cache){_db = db;_logger = logger;_cache = cache;}[HttpGet]public async Task<ActionResult<PagedResult<Book>>> Get([FromQuery] BookFilter filter){string cacheKey = $"books_{filter.GetCacheKey()}_{filter.SortBy}";try{if (!_cache.TryGetValue(cacheKey, out PagedResult<Book> result)){// 1. 应用过滤器var query = _db.Books.ApplyFilter(filter);// 2. 动态排序(依赖 System.Linq.Dynamic.Core)if (!string.IsNullOrWhiteSpace(filter.SortBy))query = query.OrderBy(filter.SortBy);elsequery = query.OrderBy("PublishedDate desc");// 3. 分页 + 总数var total = await query.CountAsync();var items = await query.Skip((filter.PageNumber - 1) * filter.PageSize).Take(filter.PageSize).ToListAsync();result = new PagedResult<Book>(total, items);// 缓存 5 分钟_cache.Set(cacheKey, result, TimeSpan.FromMinutes(5));}return Ok(result);}catch (ArgumentException ex){_logger.LogWarning(ex, "Invalid filter parameter");return BadRequest("请求参数错误");}catch (DbUpdateException ex){_logger.LogError(ex, "Database update failure");return StatusCode(503, "服务暂不可用");}catch (Exception ex){_logger.LogError(ex, "Unexpected error");return StatusCode(500, "查询失败");}}
}// 分页结果模型
public record PagedResult<T>(int Total, List<T> Items);

🌐 示例请求与响应

GET /api/books?Author=alice&MinPages=110&SortBy=PageCount%20desc&PageSize=5&PageNumber=1
{"total": 25,"items": [{ "id": "guid", "title": "Book 48", "author": "Alice", "publishedDate": "2025-05-02T00:00:00", "pageCount": 148 },...]
}

🧪 单元测试示例(xUnit)

public class BookFilterTests
{[Fact]public void ApplyFilter_ShouldFilterByTitle(){// Arrangevar data = new[]{new Book { Title = "alice" },new Book { Title = "bob" }}.AsQueryable();var filter = new BookFilter { Title = "ali" };// Actvar result = data.ApplyFilter(filter).ToList();// AssertAssert.Single(result);Assert.Equal("alice", result[0].Title);}
}

📊 最佳实践小结

维度建议
性能开启表达式缓存;合理设置缓存过期
安全性DTO 参数加 [Range] 限制;细粒度异常返回
可维护性提取 DbSeederPagedResult<T>IBookRepository 等;分层结构
文档体验Mermaid 图导出为图片;示例请求/响应;代码高亮
扩展性动态排序(System.Linq.Dynamic.Core);分布式/共享缓存方案
可测试性单元测试覆盖过滤逻辑;集成测试验证 API 行为

相关文章:

  • 4.0/Q2,GBD数据库最新文章解读
  • PostIn V1.1.2版本发布,新增接口评审功能,提升接口质量与合理性
  • Android 代码阅读环境搭建:VSCODE + SSH + CLANGD(详细版)
  • QPushButton设置菜单
  • [原创](Windows使用技巧): Windwos11如何设置局域网共享访问? (多图详解)
  • MFA多因素认证与TOTP算法核心解析(含Java案例)
  • [正点原子]ESP32S3 RGB屏幕移植LVGL
  • windows下安装docker、dify、ollama
  • C语言面试题【01】
  • 进程间通信及管道(理论)
  • OpenLayers 图形绘制
  • 【创意Python代码】
  • 集成LR1121+ESP32-S3芯片方案的EoRa-HUB系列开发板简介
  • 支持功能安全ASIL-B的矩阵管理芯片IS32LT3365,助力ADB大灯系统轻松实现功能安全等级
  • cocosCreator 1.8 升级到 2.4
  • 【PyTroch学习-001】从一个简单示例开始:手写数字识别
  • 写作-- 复合句练习
  • Python训练营打卡Day40(2025.5.30)
  • Java System类核心用法详解
  • Nginx Lua模块(OpenResty)实战:动态化、智能化你的Nginx,实现复杂Web逻辑 (2025)
  • 手机网站优势/网络广告策划书范文
  • 做网站代理能赚钱吗/关键词排名优化公司哪家强
  • 手机云电脑/seo下拉优化
  • 静态班级网站/企业培训体系搭建
  • 网站建设模板制作/湖南有实力seo优化
  • 网站建设网络推广首选公司/深圳做网站的公司