eShopOnWeb商品查询拆解:Specification模式动态过滤与分页完整指南
eShopOnWeb商品查询拆解Specification模式动态过滤与分页完整指南【免费下载链接】eShopOnWebSample ASP.NET Core 8.0 reference application, now community supported: https://github.com/NimblePros/eShopOnWeb项目地址: https://gitcode.com/gh_mirrors/es/eShopOnWeb eShopOnWeb 是一个基于 ASP.NET Core 8.0 的开源电商参考应用它的商品查询功能完整演示了Specification规约模式如何实现动态过滤与分页。本文带你从请求入口一路追踪到数据库条件拼接看它是如何用不到 20 行代码写出品牌类型页码组合查询的——全程几乎不用写 SQL 拼接代码。为什么需要 Specification 模式在传统写法里按品牌筛选 按类型筛选 分页往往要写一个带一堆if判断的查询方法参数组合一多代码就成了面条每加一个筛选条件就要改方法签名和内部逻辑查询条件散落在各处难以复用、难以单独测试Specification 模式的思路是把查什么封装成一个个可复用的对象。每个筛选规则是一个独立的小类查询执行器负责把它翻译成 SQL。规则之间互不影响随便组合。eShopOnWeb 使用的是社区流行的Ardalis.Specification库所有规约类集中在 Specifications 目录下。查询全链路从 URL 参数到 SQL一次商品列表请求的流转路径非常清晰用户在首页选择品牌、类型并翻页浏览器带上pageId、BrandFilterApplied等查询参数页面模型 Index.cshtml.cs 的OnGet接收参数转交给服务层服务层 CatalogViewModelService.cs 构建 Specification 对象调用仓储执行查询仓储将 Specification 翻译成数据库查询条件并返回结果拆解 4 个核心 Specification 类商品相关的规约共有 4 个都是小而美1️⃣ 动态过滤CatalogFilterSpecificationCatalogFilterSpecification.cs 是整个过滤的核心全部逻辑就一行WhereQuery.Where(i (!brandId.HasValue || i.CatalogBrandId brandId) (!typeId.HasValue || i.CatalogTypeId typeId));技巧在于!brandId.HasValue ||这个短路判断参数没传时该条件自动失效传了才生效。两个参数任意组合都传、只传一个、都不传一个类全部覆盖这就是动态过滤的精髓。2️⃣ 过滤 分页CatalogFilterPaginatedSpecificationCatalogFilterPaginatedSpecification.cs 在相同过滤条件上追加了.Skip(skip).Take(take)负责只取当前页数据。它还处理了一个细节当take为 0 时自动改为int.MaxValue相当于返回全部避免分页参数异常时查不到数据。3️⃣ 按 ID 批量查CatalogItemsSpecificationCatalogItemsSpecification.cs 接收一组 ID用于购物车结算等场景按 ID 批量取出商品params int[] ids让调用侧可以传入任意数量。4️⃣ 按名称查CatalogItemNameSpecificationCatalogItemNameSpecification.cs 按商品名精确查找管理端编辑商品时用来防止重名。分页是怎么算出来的真正的分页数学发生在服务层 CatalogViewModelService.cs 的GetCatalogItems方法里取当前页数据new CatalogFilterPaginatedSpecification(itemsPage * pageIndex, itemsPage, brandId, typeId)—— 页码 × 每页条数就是Skip的偏移量每页条数取自 Constants.cs 中的ITEMS_PER_PAGE 10取总数单独用一个纯过滤的CatalogFilterSpecification执行CountAsync只数数量不取实体性能友好算总页数总数 ÷ 每页条数向上取整连同当前页码一起装进 PaginationInfoViewModel.cs注意这里取数据和数总数用了两个不同的 Specification——一个带分页、一个不带各取所需。这正是规约对象可以随意裁剪、组合的威力。前端分页条条件自动跟随分页链接由 _pagination.cshtml 渲染它的巧妙之处在于把当前请求的全部查询参数原样复制到新链接上只替换pageId。也就是说你正在按品牌 A 类型 B筛选翻页后筛选条件依然保留用户不会莫名其妙看到全部商品。总结这套设计值得抄作业的地方✅规则即对象每个筛选条件是独立类加新规则零侵入 ✅参数可空即可选!xxx.HasValue ||让动态条件一行搞定 ✅取数与计数分离分页查询和总数查询各司其职 ✅分层清晰页面模型只管传参服务层构建规约仓储只管执行所有规格源码都在 src/ApplicationCore/Specifications/单元测试覆盖了大部分规约见 tests/UnitTests/ApplicationCore/Specifications/。想在自己项目里落地同样的动态过滤与分页照这个一个条件一个类的结构抄即可。【免费下载链接】eShopOnWebSample ASP.NET Core 8.0 reference application, now community supported: https://github.com/NimblePros/eShopOnWeb项目地址: https://gitcode.com/gh_mirrors/es/eShopOnWeb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考