ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Ultimate ASP.NET CORE 6.0 Web API --- 读书笔记(16)

2022-06-16 19:33:57  阅读:156  来源: 互联网

标签:CORE ASP pageSize 读书笔记 int get set pageNumber public


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有