使用Sieve包实现WebApi分页时的问题及求解
CQRS+MediatR架构下Sieve.net分页实现问题
我正在开发一个采用CQRS和MediatR模式的小型WebApi作为求职作品集,目前用Sieve.net做结果过滤、排序和分页时遇到了分页相关问题。
期望返回格式
{ "currentPage": 1, "pageSize": 5, "pageCount": 1, "rowCount": 5, "data": [ { "id": 1, "name": "name", "description": "description" } ] }
现有基础代码
PagedRequestHandler基类
public abstract class PagedRequestHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse> { public abstract Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken); }
PagedResponseExtension扩展类
public static class PagedResponseExtension { public static async Task<PagedResponse<TResponse>> ToPagedAsync<TEntity, TResponse> (this IQueryable<TEntity> query, IMapper mapper, ISieveProcessor sieve, SieveModel model = null, CancellationToken cancellationToken = default) where TResponse : ResponseBase<TResponse> { var page = model?.Page ?? 1; var pageSize = model?.PageSize ?? 50; if (model != null) query = sieve.Apply(model, query, applyPagination: false); var rowCount = await query.CountAsync(cancellationToken); var pageCount = (int)Math.Ceiling((double)rowCount / pageSize); var skip = (page - 1) * pageSize; var pagedQuery = query.Skip(skip).Take(pageSize); var response = new PagedResponse<TResponse> { CurrentPage = page, PageSize = pageSize, PageCount = pageCount, RowCount = rowCount }; response.Results = await pagedQuery.ProjectTo<TResponse>(mapper.ConfigurationProvider) .ToListAsync(cancellationToken); return response; } }
PagedResponse类
public class PagedResponse<TResponse> where TResponse : class { public int CurrentPage { get; set; } public int PageSize { get; set; } public int PageCount { get; set; } public long RowCount { get; set; } public IList<TResponse> Results { get; set; } = new List<TResponse>(); public ErrorModel Error { get; internal set; } }
GetProductsQuery查询类
public class GetProductsQuery : QueryBaseWithSieve<List<Product>> { public SieveModel SieveModel { get; init; } public async override Task<List<Product>> Execute(FlowerShopStorageContext context, ISieveProcessor sieveProcessor) { var query = sieveProcessor.Apply(SieveModel, context.Products.AsNoTracking()); return await query.ToListAsync(); } }
当前的GetProductsHandler处理类
public class GetProductsHandler : IRequestHandler<GetProductsRequest, GetProductsResponse> { private readonly IMapper mapper; private readonly IQueryExecutor queryExecutor; public GetProductsHandler(IMapper mapper, IQueryExecutor queryExecutor) { this.mapper = mapper; this.queryExecutor = queryExecutor; } public async Task<GetProductsResponse> Handle(GetProductsRequest request, CancellationToken cancellationToken) { var query = new GetProductsQuery() { SieveModel = request.SieveModel }; var products = await this.queryExecutor.ExecuteWithSieve(query); if (products == null) { return new GetProductsResponse() { Error = new ErrorModel(ErrorType.NotFound) }; } var mappedProducts = this.mapper.Map<List<Domain.Models.ProductDTO>>(products); var response = new GetProductsResponse() { Data = mappedProducts }; return response; } }
尝试修改后的错误
我修改了GetProductsHandler,但遇到编译错误:
public class GetProductsHandler : PagedRequestHandler<GetProductsRequest, PagedResponse<GetProductsResponse>> { private readonly IMapper mapper; private readonly IQueryExecutor queryExecutor; private readonly SieveProcessor sieveProcessor; public GetProductsHandler(IMapper mapper, IQueryExecutor queryExecutor, SieveProcessor sieveProcessor) { this.mapper = mapper; this.queryExecutor = queryExecutor; this.sieveProcessor = sieveProcessor; } public override async Task<PagedResponse<GetProductsResponse>> Handle(GetProductsRequest request, CancellationToken cancellationToken) { var query = new GetProductsQuery() { SieveModel = request.SieveModel }; var products = await this.queryExecutor.ExecuteWithSieve(query); if (products == null) { return new PagedResponse<GetProductsResponse>() { Error = new ErrorModel(ErrorType.NotFound) }; } products.AsQueryable(); // var mappedProducts = this.mapper.Map<List<Domain.Models.ProductDTO>>(products); var response = new PagedResponse<GetProductsResponse>() { //Results = products // Data = mappedProducts //Results = (IList<GetProductsResponse>)products //mappedProducts //products.ToList() }; // 错误 CS1929 'PagedResponse<GetProductsResponse>' 不包含 'ToPagedAsync' 的定义,最佳扩展方法重载 // 'PagedResponseExtension.ToPagedAsync<GetProductsRequest, GetProductsResponse>(IQueryable<GetProductsRequest>, IMapper, ISieveProcessor, SieveModel, CancellationToken)' // 需要接收类型 'IQueryable<GetProductsRequest>' return await response.ToPagedAsync<GetProductsRequest, GetProductsResponse>(query, mapper, sieveProcessor, request.SieveModel); //return response.ToPagedAsync<GetProductsRequest, GetProductsResponse>(); } }
控制器中的错误
同时在ProductsController里也遇到了错误:
类型'Shop.ApplicationServices.API.Domain.Product.GetProductsRequest'无法用作泛型类型或方法'ApiControllerBase.HandleRequest<TRequest, TResponse>(TRequest)'的类型参数'TRequest'。不存在从'Shop.ApplicationServices.API.Domain.Product.GetProductsRequest'到'MediatR.IRequest<Shop.ApplicationServices.API.Domain.Product.GetProductsResponse>'的隐式引用转换。
控制器代码:
[HttpGet] [Route("")] public async Task<IActionResult> GetAllProducts([FromQuery] SieveModel sieveModel) { GetProductsRequest request = new GetProductsRequest { SieveModel = sieveModel }; return await this.HandleRequest<GetProductsRequest, GetProductsResponse>(request); }
提问
请问我当前的解决思路是否正确?
内容的提问来源于stack exchange,提问作者luca88
相关产品推荐
相关产品推荐

