網站首頁 編程語言 正文
需求
查詢中有個非常常見的需求就是后端分頁,實現的方式也不算復雜,所以我們本文僅僅演示一個后端查詢分頁的例子。
目標
實現分頁查詢返回。
原理與思路
對于分頁查詢而言,我們需要在請求中獲取當前請求的是第幾頁,每頁請求多少項數據。在返回值中需要告訴前端,當前這一頁的所有數據項列表,總共的數據項有多少。為此我們可以定義一個包裝類型,供系統中所有需要提供后端分頁查詢返回值使用。
除了最基本的實現方式之外,我們可能還需要實現關于分頁數據結構的AutoMapper轉換映射,避免手動重復實現。
實現
定義分頁結果數據結構
我們在Application/Common/Models
中定義一個類,表示分頁結果。
PaginatedList.cs
using Microsoft.EntityFrameworkCore; namespace TodoList.Application.Common.Models; public class PaginatedList<T> { public List<T> Items { get; } public int PageNumber { get; } public int TotalPages { get; } public int TotalCount { get; } public PaginatedList(List<T> items, int count, int pageNumber, int pageSize) { PageNumber = pageNumber; TotalPages = (int)Math.Ceiling(count / (double)pageSize); TotalCount = count; Items = items; } // 增加屬性表示是否有前一頁 public bool HasPreviousPage => PageNumber > 1; // 增加屬性表示是否有后一頁 public bool HasNextPage => PageNumber < TotalPages; // 分頁結果構建輔助方法 public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageNumber, int pageSize) { var count = await source.CountAsync(); // 注意我們給的請求中pageNumber是從1開始的 var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync(); return new PaginatedList<T>(items, count, pageNumber, pageSize); } }
添加對于分頁結果的Mapping Profile
在Application/Common/Mappings
中新增一個類用于實現關于分頁結果的擴展方法:
MappingExtensions.cs
using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; using TodoList.Application.Common.Models; namespace TodoList.Application.Common.Mappings; public static class MappingExtensions { public static Task<PaginatedList<TDestination>> PaginatedListAsync<TDestination>(this IQueryable<TDestination> queryable, int pageNumber, int pageSize) { return PaginatedList<TDestination>.CreateAsync(queryable, pageNumber, pageSize); } public static Task<List<TDestination>> ProjectToListAsync<TDestination>(this IQueryable queryable, IConfigurationProvider configuration) { return queryable.ProjectTo<TDestination>(configuration).ToListAsync(); } }
創建分頁查詢請求
為了演示分頁查詢的應用,我們新增一個允許分頁查詢TodoItem
的Query
:
GetTodoItemsWithPaginationQuery.cs
using System.Linq; using AutoMapper; using AutoMapper.QueryableExtensions; using MediatR; using TodoList.Application.Common.Interfaces; using TodoList.Application.Common.Mappings; using TodoList.Application.Common.Models; using TodoList.Application.TodoItems.Specs; using TodoList.Domain.Entities; namespace TodoList.Application.TodoItems.Queries.GetTodoItems; public class GetTodoItemsWithPaginationQuery : IRequest<PaginatedList<TodoItemDto>> { public Guid ListId { get; set; } public int PageNumber { get; set; } = 1; public int PageSize { get; set; } = 10; } public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler<GetTodoItemsWithPaginationQuery, PaginatedList<TodoItemDto>> { private readonly IRepository<TodoItem> _repository; private readonly IMapper _mapper; public GetTodoItemsWithPaginationQueryHandler(IRepository<TodoItem> repository, IMapper mapper) { _repository = repository; _mapper = mapper; } public async Task<PaginatedList<TodoItemDto>> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) { return await _repository .GetAsQueryable(x => x.ListId == request.ListId) .OrderBy(x => x.Title) .ProjectTo<TodoItemDto>(_mapper.ConfigurationProvider) .PaginatedListAsync(request.PageNumber, request.PageSize); } }
創建查詢Controller
TodoItemController.cs
// 對于查詢來說,一般參數是來自查詢字符串的,所以這里用[FromQuery] [HttpGet] public async Task<ApiResponse<PaginatedList<TodoItemDto>>> GetTodoItemsWithPagination([FromQuery] GetTodoItemsWithPaginationQuery query) { return ApiResponse<PaginatedList<TodoItemDto>>.Success(await _mediator.Send(query)); }
驗證
啟動Api
項目,執行創建TodoList
的請求:
請求
響應
總結
對于后端排序的需求來說,實現起來并不復雜,但是在這個分頁的過程中,要注意一定要以某個不會輕易變動的字段來作為排序的鍵,否則會在多次請求后續頁的過程中出現因為字段變動導致排序結果變動進而引發分頁結果的前后不一致的情況。
原文鏈接:https://www.cnblogs.com/code4nothing/p/build-todolist-13.html
相關推薦
- 2022-11-01 Flask路由尾部有沒有斜杠有什么區別_python
- 2022-07-07 Python數據分析之?Matplotlib?3D圖詳情_python
- 2022-09-13 Nginx如何限制IP訪問只允許特定域名訪問_nginx
- 2024-04-06 linux中redis重啟,啟動,停止的sh腳本
- 2022-07-01 C語言詳細講解strcpy?strcat?strcmp函數的模擬實現_C 語言
- 2022-11-15 關于if?exists的用法及說明_MsSql
- 2024-01-15 jquery獲取dom元素身上的綁定事件
- 2022-06-06 typescript封裝屬性、public、private、protected、constructo
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支