• 学习笔记02:翻页 过滤 排序


    1 翻页

    Query String  http://localhost:5000/api/posts?pageIndex=2&pageSize=10&orderBy=Id

    1.1数据分页

    1.建立 QueryParameters.cs 数据分页方法类 包含.pageIndex, pageSize, orderBy 等分页参数 
    
    2.建立PostParameters.cs post专用的分页类,继承自QueryParameters.cs 即可.(无特殊条件可以不用写其他内容,继承功能够用即可)

    3.1把PostParameters 传给PostController.cs 的[HttpGet] 如下:
    public async Task<IActionResult> Get(PostParameters postParameters)
    3.2把postParameters传给PostController.cs具体的实现方法
    原来:
    var postList = await _postRepository.GetAllPostAsync();
    改为:
    var postList = await _postRepository.GetAllPostAsync(postParameters);
    3.3给接口添加参数
    同时修改接口
    原来:
    Task<PaginatedList<Post>> GetAllPostAsync();
    改为:
    Task<PaginatedList<Post>> GetAllPostAsync(PostParameters postParameters);
    3.4在实现类添加参数 PostParameters postParameters,同时原来的列表方法修改下如下
    原来为直接列出列表数据.
    return await _myContext.Post.ToListAsync();
    改为:
    1.按Id排序
    var query = _myContext.Post.OrderBy(x => x.Id);
    
    2.数据分页
    var data = await query.Skip(postParameters.PageIndex * postParameters.PageSize)
    .Take(postParameters.PageSize).ToListAsync();

     1.2分页按钮(不含上一页 下一页) ,定义一个PageList.cs 记录 翻页数据

        public class PaginatedList<T> : List<T> where T : class
        {
            public int PageSize { get; set; }
            public int PageIndex { get; set; }
    
            private int _totalItemsCount;
            public int TotalItemsCount
            {
                get => _totalItemsCount;
                set => _totalItemsCount = value >= 0 ? value : 0;
            }
    
            public int PageCount => TotalItemsCount / PageSize + (TotalItemsCount % PageSize > 0 ? 1 : 0);
    
            public bool HasPrevious => PageIndex > 0;
            public bool HasNext => PageIndex < PageCount - 1;
    
            public PaginatedList(int pageIndex, int pageSize, int totalItemsCount, IEnumerable<T> data)
            {
                PageIndex = pageIndex;
                PageSize = pageSize;
                TotalItemsCount = totalItemsCount;
                AddRange(data);
            }
        }

    修改PostRepository.cs
    原返回类型:
    public async Task<IEnumerable<Post>> GetAllPostAsync(PostParameters postParameters)
    修改为:
    public async Task<PaginatedList<Post>> GetAllPostAsync(PostParameters postParameters)
    同时修改对应的接口的返回类型.


    再修改PostRepository.cs 具体的代码
    1.统计出总条数
    var count = await query.CountAsync();

    2.把原来的返回数据返回给一个变量如 var data
    var data = await query.Skip(postParameters.PageIndex * postParameters.PageSize)
    .Take(postParameters.PageSize).ToListAsync();

      3.以上信息组合成返回数据

     return new PaginatedList<Post>(postParameters.PageIndex,postParameters.PageSize,count,data);

      4.在PostController创建匿名类 ,并将属性名改成首字母小写.(new部分负责)

    var meta = new
                {
                    Pagesize = postList.PageSize,
                    Pageindex = postList.PageIndex,
                    TotalItemsCount = postList.TotalItemsCount,
                    PageCount = postList.PageCount
                };
    
                Response.Headers.Add("x-Pagination",JsonConvert.SerializeObject(meta,new JsonSerializerSettings()
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                }));

    1.3分页 上一页 下一页 

    使用IUrlHelper  用之前需要配置 IActionContextAccessor 这个东西,在Controller里写一个自定义的方法返回前一页 后一页.

    1.创建一个枚举类PaginationResourceUriType.cs
    namespace BlogDemo.Core.Entities { public enum PaginationResourceUriType { CurrentPage, PreviousPage, NextPage } }

    2.startup注册IUrlHelper

                //注册UrlHelper
                services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
                services.AddScoped<IUrlHelper>(factory =>
                {
                    var actionContext = factory.GetService<IActionContextAccessor>().ActionContext;
                    return new UrlHelper(actionContext);
                });

    3.在PostController里添加一个创建Url的方法
            private string CreatePostUri(PostParameters parameters, PaginationResourceUriType uriType)
            {
                switch (uriType)
                {
                    case PaginationResourceUriType.PreviousPage:
                        var previousParameters = new
                        {
                            pageIndex = parameters.PageIndex - 1,
                            pageSize = parameters.PageSize,
                            orderBy = parameters.OrderBy,
                            fields = parameters.Fields
                        };
                        return _urlHelper.Link("GetPosts", previousParameters);
                    case PaginationResourceUriType.NextPage:
                        var nextParameters = new
                        {
                            pageIndex = parameters.PageIndex + 1,
                            pageSize = parameters.PageSize,
                            orderBy = parameters.OrderBy,
                            fields = parameters.Fields
                        };
                        return _urlHelper.Link("GetPosts", nextParameters);
                    default:
                        var currentParameters = new
                        {
                            pageIndex = parameters.PageIndex,
                            pageSize = parameters.PageSize,
                            orderBy = parameters.OrderBy,
                            fields = parameters.Fields
                        };
                        return _urlHelper.Link("GetPosts", currentParameters);
                }
            }

      给[HttpGet]起个名字   [HttpGet(Name = "GetPosts")]  针对这个名字的 Get操作

      4.在匿名类上生成前一页后一页连接,并将生成的  previousPageLink  nextPageLink添加到元数据.

                var previousPageLink = postList.HasPrevious ?
                    CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null;
    
                var nextPageLink = postList.HasNext ?
                    CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;

    调试查看结果

    2.过滤  条件应用于Resource Model.

    过滤: 对集合资源附加一些条件, 筛选出结果.如: http://localhost:5000/api/countries?englishName=China.
    过滤属性可以放在QueryParameters的子类里.


    搜索: 使用关键字对集合资源进行模糊搜索.
    http://localhost/api/countries?searchTerm=hin

    2.1 在PostParameters增加一个Title属性.(Post实体里有)   

     public string Title { get; set; }

    2.2 然后在PostRepository进行过滤

    原来:
    var query = _myContext.Post.OrderBy(x => x.Id);
    修改:将query先出集合数据,再排序.中间加上条件判断.
    var query = _myContext.Post.AsQueryable(); if (!string.IsNullOrEmpty(postParameters.Title)) { var title = postParameters.Title.ToLowerInvariant(); query = query.Where(x => x.Title.ToLowerInvariant().Contains(title)); } query=query.OrderBy(x => x.Id);

    执行调试  如:https://localhost:5001/api/posts?pageindex=0&pagesize=3&title=Post Title 4

     3.排序   在Infrastructure里安装System.Linq.Dynamic.Core

    排序思路:建立三层的服务.

    第一层 容器层:PropertyMappingContainer   

        PostResource 到 Post他两之间属性有一些映射,我们把它两之间的属性映射算成一对,注册到这个容器.

    第二层:他两之间的属性映射PropertyMapping(PostPropertyMapping)

    第三次:具体到每个映射的属性MappedProperty

    Services文件夹下的cs文件解析,常规的,不需要改变,项目组复制使用即可.

    1.1.MappedProperty.cs  Resource和Entity   要求字段要对应:名字(Name) ,           //排序是否是相反的(Revert).

        public class MappedProperty
        {
            public string Name { get; set; }
            public bool Revert { get; set; }
        }

    1.2 PropertyMapping.cs 两个表之间的映射关系.

        Resources/PostPropertyMapping.cs 继承PropertyMapping.cs  且实现两表之间的具体映射.

        public class PostPropertyMapping : PropertyMapping<PostResource, Post>
        {
            public PostPropertyMapping() : base(
                new Dictionary<string, List<MappedProperty>>
                    (StringComparer.OrdinalIgnoreCase)
                    {
                        [nameof(PostResource.Title)] = new List<MappedProperty>
                        {
                            new MappedProperty{ Name = nameof(Post.Title), Revert = false}
                        },
                        [nameof(PostResource.Body)] = new List<MappedProperty>
                        {
                            new MappedProperty{ Name = nameof(Post.Body), Revert = false}
                        },
                        [nameof(PostResource.Author)] = new List<MappedProperty>
                        {
                            new MappedProperty{ Name = nameof(Post.Author), Revert = false}
                        }
                    })
            {
            }
        }

    1.3使用容器

    1.4startup注册

    1.5使用排序,在Infrastructure项目建立 Extensions/QueryableExtensions.cs类.

    1.6在PostRepository添加 IPropertyMappingContainer构造函数.再修改如下注释的代码

                //query = query.OrderBy(x => x.Id);
                query = query.ApplySort(postParameters.OrderBy, _propertyMappingContainer.Resolve<PostResource, Post>());
  • 相关阅读:
    jdk版本切换
    Java开发中遇到的问题
    递归删除文件夹
    重写equals方法
    JSP基础
    js把变量转换成json数据
    myBatista批量查询和插入
    Jquery密码强度校验
    Linux配置外网访问mysql
    linux下开启、关闭、重启mysql服务命令
  • 原文地址:https://www.cnblogs.com/dxh0535/p/10414071.html
Copyright © 2020-2023  润新知