Ultimate ASP.NET CORE 6.0 Web API --- 读书笔记(16)
作者:互联网
16 Paging
本文内容来自书籍: Marinko Spasojevic - Ultimate ASP.NET Core Web API - From Zero To Six-Figure Backend Developer (2nd edition)
分页的意思是,只是返回部分结果的API,返回所有结果不仅仅是非常无效的,而且对应用和硬件有着毁灭性的影响。还有客户端的资源一般都是有限的,必须限制展示的数据
16.2 Paging Implementation
我们不希望改变base repository
的逻辑或者实现任何业务逻辑在控制器当中
我们希望URI是这样的
https://localhost:5001/api/companies/companyId/employees?pageNumber=2&pageSize=2
而且,即使客户端的请求是:
https://localhost:5001/api/companies/companyId/employees
我们也要约束我们的API,而不是返回所有的数据
所以现在我们开始修改controller
我们需要一个包装着查询参数的DTO
// 首先创建一个分页参数的基类
public abstract class RequestParameters
{
private const int MaxPageSize = 50;
public int PageNumber { get; set; } = 1;
private int _pageSize = 10;
public int PageSize
{
get => _pageSize;
set => _pageSize = value > MaxPageSize ? MaxPageSize : value;
}
}
public class EmployeeParameters : RequestParameters
{
}
[HttpGet]
public async Task<IActionResult> GetEmployeesForCompany(Guid companyId,
[FromQuery] EmployeeParameters employeeParameters)
{
var employees = await _service.EmployeeService.GetEmployeesAsync(companyId,
trackChanges: false);
return Ok(employees);
}
[FromQuery]
,查询参数
可以对分页的参数进一步封装
public class MetaData
{
public int CurrentPage { get; set; }
public int TotalPages { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public bool HasPrevious => CurrentPage > 1;
public bool HasNext => CurrentPage < TotalPages;
}
public class PagedList<T> : List<T>
{
public MetaData MetaData { get; set; }
public PagedList(IEnumerable<T> items, int count, int pageNumber, int pageSize)
{
MetaData = new MetaData
{
TotalCount = count,
PageSize = pageSize,
CurrentPage = pageNumber,
TotalPages = (int)Math.Ceiling(count / (double)pageSize)
};
AddRange(items);
}
public static PagedList<T> ToPagedList(IEnumerable<T> source, int pageNumber, int
pageSize)
{
var enumerable = source.ToList();
var count = enumerable.Count;
var items = enumerable
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize).ToList();
return new PagedList<T>(items, count, pageNumber, pageSize);
}
}
然后在响应的时候,需要将这个元数据也一并返回
[HttpGet]
public async Task<IActionResult> GetEmployeesForCompany(Guid companyId,
[FromQuery] EmployeeParameters employeeParameters)
{
var pagedResult =
await _service.EmployeeService.GetEmployeesAsync(companyId, employeeParameters, trackChanges: false);
Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(pagedResult.metaData));
return Ok(pagedResult.employees);
}
但是上面的方案,存在一个性能问题,当数据库的数据达到千万级别的时候,就会很慢,因为在分页之前,首先是获取的ID相关的数据,也就是某一个ID的全部数据,然后再创建分页实体,过滤数据;当面对很多数据的时候,我们需要在数据库查询的时候,就已经做出过滤的动作,使得筛选放到数据库,而不是APP中,这样的性能会好很多
还有就是,我们需要让客户端读取我们的新的响应头X-Pagination
,我们需要更改CORS
的配置
public static void ConfigureCors(this IServiceCollection services) =>
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder =>
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("X-Pagination"));
});
标签:CORE,ASP,pageSize,读书笔记,int,get,set,pageNumber,public 来源: https://www.cnblogs.com/huangwenhao1024/p/16383191.html