.NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)查詢分頁(yè)
需求
查詢中有個(gè)非常常見(jiàn)的需求就是后端分頁(yè),實(shí)現(xiàn)的方式也不算復(fù)雜,所以我們本文僅僅演示一個(gè)后端查詢分頁(yè)的例子。
目標(biāo)
實(shí)現(xiàn)分頁(yè)查詢返回。
原理與思路
對(duì)于分頁(yè)查詢而言,我們需要在請(qǐng)求中獲取當(dāng)前請(qǐng)求的是第幾頁(yè),每頁(yè)請(qǐng)求多少項(xiàng)數(shù)據(jù)。在返回值中需要告訴前端,當(dāng)前這一頁(yè)的所有數(shù)據(jù)項(xiàng)列表,總共的數(shù)據(jù)項(xiàng)有多少。為此我們可以定義一個(gè)包裝類型,供系統(tǒng)中所有需要提供后端分頁(yè)查詢返回值使用。
除了最基本的實(shí)現(xiàn)方式之外,我們可能還需要實(shí)現(xiàn)關(guān)于分頁(yè)數(shù)據(jù)結(jié)構(gòu)的AutoMapper轉(zhuǎn)換映射,避免手動(dòng)重復(fù)實(shí)現(xiàn)。
實(shí)現(xiàn)
定義分頁(yè)結(jié)果數(shù)據(jù)結(jié)構(gòu)
我們?cè)?code>Application/Common/Models中定義一個(gè)類,表示分頁(yè)結(jié)果。
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;
}
// 增加屬性表示是否有前一頁(yè)
public bool HasPreviousPage => PageNumber > 1;
// 增加屬性表示是否有后一頁(yè)
public bool HasNextPage => PageNumber < TotalPages;
// 分頁(yè)結(jié)果構(gòu)建輔助方法
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageNumber, int pageSize)
{
var count = await source.CountAsync();
// 注意我們給的請(qǐng)求中pageNumber是從1開(kāi)始的
var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageNumber, pageSize);
}
}
添加對(duì)于分頁(yè)結(jié)果的Mapping Profile
在Application/Common/Mappings中新增一個(gè)類用于實(shí)現(xiàn)關(guān)于分頁(yè)結(jié)果的擴(kuò)展方法:
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();
}
}創(chuàng)建分頁(yè)查詢請(qǐng)求
為了演示分頁(yè)查詢的應(yīng)用,我們新增一個(gè)允許分頁(yè)查詢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);
}
}
創(chuàng)建查詢Controller
TodoItemController.cs
// 對(duì)于查詢來(lái)說(shuō),一般參數(shù)是來(lái)自查詢字符串的,所以這里用[FromQuery]
[HttpGet]
public async Task<ApiResponse<PaginatedList<TodoItemDto>>> GetTodoItemsWithPagination([FromQuery] GetTodoItemsWithPaginationQuery query)
{
return ApiResponse<PaginatedList<TodoItemDto>>.Success(await _mediator.Send(query));
}驗(yàn)證
啟動(dòng)Api項(xiàng)目,執(zhí)行創(chuàng)建TodoList的請(qǐng)求:
請(qǐng)求

響應(yīng)

總結(jié)
對(duì)于后端排序的需求來(lái)說(shuō),實(shí)現(xiàn)起來(lái)并不復(fù)雜,但是在這個(gè)分頁(yè)的過(guò)程中,要注意一定要以某個(gè)不會(huì)輕易變動(dòng)的字段來(lái)作為排序的鍵,否則會(huì)在多次請(qǐng)求后續(xù)頁(yè)的過(guò)程中出現(xiàn)因?yàn)樽侄巫儎?dòng)導(dǎo)致排序結(jié)果變動(dòng)進(jìn)而引發(fā)分頁(yè)結(jié)果的前后不一致的情況。
到此這篇關(guān)于.NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)查詢分頁(yè)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- .NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)ActionFilter
- .NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)接口請(qǐng)求驗(yàn)證
- .NET?6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)DELETE請(qǐng)求與HTTP請(qǐng)求冪等性
- .NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)PUT請(qǐng)求
- .NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)全局異常處理
- .NET 6開(kāi)發(fā)TodoList應(yīng)用之使用AutoMapper實(shí)現(xiàn)GET請(qǐng)求
- .NET?6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)Repository模式
- .NET?6開(kāi)發(fā)TodoList應(yīng)用之使用MediatR實(shí)現(xiàn)POST請(qǐng)求
- .NET 6開(kāi)發(fā)TodoList應(yīng)用引入數(shù)據(jù)存儲(chǔ)
- .NET?6開(kāi)發(fā)TodoList應(yīng)用引入第三方日志庫(kù)
- .NET 6開(kāi)發(fā)TodoList應(yīng)用實(shí)現(xiàn)結(jié)構(gòu)搭建
- .NET?6開(kāi)發(fā)TodoList應(yīng)用實(shí)現(xiàn)系列背景
- 使用.NET?6開(kāi)發(fā)TodoList應(yīng)用之引入數(shù)據(jù)存儲(chǔ)的思路詳解
- 使用.NET?6開(kāi)發(fā)TodoList應(yīng)用之領(lǐng)域?qū)嶓w創(chuàng)建原理和思路
- .NET?6開(kāi)發(fā)TodoList應(yīng)用之請(qǐng)求日志組件HttpLogging介紹
相關(guān)文章
NetCore實(shí)現(xiàn)全局模型綁定異常信息統(tǒng)一處理(場(chǎng)景分析)
本文主要講解NetCore如何使用中間件捕獲模型綁定的異常信息,對(duì)NetCore實(shí)現(xiàn)全局模型綁定異常信息統(tǒng)一處理場(chǎng)景分析及實(shí)現(xiàn)代碼感興趣的朋友一起看看吧2021-12-12
.Net 調(diào)用存儲(chǔ)過(guò)程取到return的返回值
存儲(chǔ)過(guò)程只能返回 int 類型,如果返回一個(gè)字符串 ,將會(huì)報(bào)類型轉(zhuǎn)化錯(cuò)誤,下面以示例介紹下如何取到return的值,需要的朋友可以參考下2014-08-08
ASP.NET 導(dǎo)出到Excel時(shí)保留換行的代碼
由于Excel畢竟不是 HTML,它有自己的樣式標(biāo)準(zhǔn),在Excel 中,實(shí)現(xiàn)換行的方法是2008-12-12
利用noesis.Javascript開(kāi)源組件.Net中執(zhí)行javascript腳本
利用Noesis.Javascript開(kāi)源組件可以做到在.net中執(zhí)行js腳本,同時(shí)js腳本也能調(diào)用C#函數(shù)。這個(gè)組件的獲得方式:在NuGet中輸入搜索"Noesis"就能找到,我們來(lái)做個(gè)搜索功能:用戶能夠在textbox中輸入js腳本來(lái)篩選list記錄2013-12-12
總結(jié)ASP.NET C#中經(jīng)常用到的13個(gè)JS腳本代碼
本文總結(jié)了ASP.NET C#在實(shí)際開(kāi)發(fā)過(guò)程中13個(gè)JS腳本代碼,方便大家在開(kāi)發(fā)中使用,希望對(duì)大家有用。2016-04-04
asp.net(c#) RSS功能實(shí)現(xiàn)代碼
這兩天一邊從網(wǎng)上找資料,自己再測(cè)試,終于完成本站的RSS功能了!先自我恭喜下!!2008-11-11

