tnblog
首页
视频
资源
登录

新型分页,排序,搜索,以及上一页与下一页

6098人阅读 2019/10/29 11:47 总访问:3467246 评论:0 收藏:1 手机
分类: .net后台框架


1.分页数据接口,方法与实现类

  1. public interface IPostRepository
  2. {
  3.     Task<PaginatedList<Post>> GetAllPosts(PostParameters postParameters);
  4.     Task<Post> GetPostByIdAsync(int id);
  5.     void AddPost(Post post);
  6. }

通过PostRepository.cs实现IPostRepository.cs类:

  1. public class PostRepository : IPostRepository
  2. {
  3.     private readonly MyContext _myContext;
  4.     public PostRepository(MyContext myContext)
  5.     {
  6.         this._myContext = myContext;
  7.     }
  8.     public void AddPost(Post post)
  9.     {
  10.         _myContext.Posts.Add(post);
  11.     }
  12.     public async Task<Post> GetPostByIdAsync(int id)
  13.     {
  14.         return await _myContext.Posts.FindAsync(id);
  15.     } 
  16.     public async Task<PaginatedList<Post>> GetAllPosts(PostParameters postParameters)
  17.     {
  18.         #region 翻页,排序
  19.         var query = _myContext.Posts.OrderBy(x => x.Id);
  20.         var count = await query.CountAsync();
  21.         #endregion
  22.         //return await _myContext.Posts.ToListAsync();
  23.         var data = await query
  24.             .Skip(postParameters.PageIndex * postParameters.PageSize)
  25.             .Take(postParameters.PageSize)
  26.             .ToListAsync();
  27.         return new PaginatedList<Post>(postParameters.PageIndex,postParameters.PageSize,count,data);
  28.     }
  29. }

PaginatedList.cs

  1. public class PaginatedList<T> : List<T> where T :class
  2. {
  3.     public int PageSize { get; set; }
  4.     public int PageIndex { get; set; }
  5.     private int _totalItemsCount;
  6.     public int TotalItemsCount
  7.     {
  8.         get=>_totalItemsCount;
  9.         set=>_totalItemsCount = value >=0?value:0;
  10.     }
  11.     public int PageCount => TotalItemsCount / PageSize + (TotalItemsCount % PageSize > 0 ? 1 : 0);
  12.     //是否有上一页
  13.     public bool HasPrevious => PageIndex > 0;
  14.     //是否有下一页
  15.     public bool HasNext => PageIndex <PageCount - 1;
  16.     public PaginatedList(int pageIndex,int pageSize,int totalItemCount,IEnumerable<T> data)
  17.     {
  18.         PageIndex = pageIndex;
  19.         PageSize = pageSize;
  20.         TotalItemsCount = totalItemCount;
  21.         AddRange(data);
  22.     }
  23. }

PostParameters.cs类实现QueryParameters.cs

  1. public abstract class QueryParameters : System.ComponentModel.INotifyPropertyChanged
  2. {
  3.     private const int DefaultPageSize = 10;
  4.     private const int DefaultMaxPageSize = 100;
  5.     private int _pageIndex;
  6.     public int PageIndex
  7.     {
  8.         get => _pageIndex;
  9.         set => _pageIndex = value >= 0 ? value : 0;
  10.     }
  11.     private int _pageSize = DefaultPageSize;
  12.     public virtual int PageSize
  13.     {
  14.         get => _pageSize;
  15.         set => SetField(ref _pageSize, value);
  16.     }
  17.     private string _orderBy;
  18.     public string OrderBy
  19.     {
  20.         get => _orderBy;
  21.         set => _orderBy = value ?? nameof(IEntity.Id);
  22.     }
  23.     private int _maxPageSize = DefaultMaxPageSize;
  24.     public event PropertyChangedEventHandler PropertyChanged;
  25.     protected internal virtual int MaxPageSize
  26.     {
  27.         get => _maxPageSize;
  28.         set => SetField(ref _maxPageSize, value);
  29.     }
  30.     public string Fields { get; set; }
  31.     protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
  32.     {
  33.         PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(propertyName));
  34.     }
  35.     protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
  36.     {
  37.         if (EqualityComparer<T>.Default.Equals(field))
  38.         {
  39.             return false;
  40.         }
  41.         field = value;
  42.         OnPropertyChanged(propertyName);
  43.         if (propertyName == nameof(PageSize) || propertyName == nameof(MaxPageSize))
  44.         {
  45.             SetPageSize();
  46.         }
  47.         return true;
  48.     }
  49.     private void SetPageSize()
  50.     {
  51.         if (_maxPageSize <= 0)
  52.         {
  53.             _maxPageSize = DefaultMaxPageSize;
  54.         }
  55.         if (_pageSize <= 0)
  56.         {
  57.             _pageSize = DefaultPageSize;
  58.         }
  59.         _pageSize = _pageSize > _maxPageSize ? _maxPageSize : _pageSize;
  60.     }
  61. }
  1. public class PostParametersQueryParameters
  2. {
  3. }

2.控制器的实现

Startup.cs类中ConfigureServices方法实现注入

  1. services.AddScoped<IPostRepository, PostRepository>();

WebApiPostController控制器

  1. private readonly IPostRepository _PostRepository;
  2. private readonly IUnitOfWOrk _unitOfWork;
  3. private readonly ILogger _Logger;
  4. private readonly IConfiguration _configuration;
  5. private readonly IMapper _mapper;
  6. public PostController(IUnitOfWOrk UnitOfWOrk
  7.     , IPostRepository PostRepository
  8.     ,ILoggerFactory loggerFactory
  9.     ,IConfiguration configuration
  10.     ,IMapper mapper
  11.     )
  12. {
  13.     this._PostRepository = PostRepository;
  14.     this._unitOfWork = UnitOfWOrk;
  15.     this._configuration = configuration;
  16.     this._mapper = mapper;
  17.     this._Logger = loggerFactory.CreateLogger("AiDaSiBlog.API.Controllers.PostController");
  18. }
  19. [HttpGet]
  20. public async Task<IActionResult> Get(PostParameters postParameters)
  21. {
  22.     var posts = await _PostRepository.GetAllPosts(postParameters);
  23.     var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(posts);
  24.     var metta = new {
  25.         Pagesize = posts.PageSize,
  26.         PageIndex = posts.PageIndex,
  27.         TotalItemsCount = posts.TotalItemsCount,
  28.         PageCount = posts.PageCount
  29.     };
  30.     //标准化
  31.     Response.Headers.Add("x-Pagination", JsonConvert.SerializeObject(metta,new JsonSerializerSettings()
  32.     {
  33.         //Json输出格式小写
  34.         ContractResolver = new CamelCasePropertyNamesContractResolver()
  35.     }));
  36.     return Ok(postResources);

结果:


3.生成前后页的Url


首先创建前后页枚举

PaginationResourceUriType.cs

  1. #region 生成前后页的的Url枚举
  2. public enum PaginationResourceUriType
  3. {
  4.     CurrentPage,
  5.     PreviousPage,
  6.     NextPage
  7. }
  8. #endregion

注册服务

  1. #region 生成前后页的的Url枚举
  2. services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
  3. services.AddScoped<IUrlHelper>(factory => {
  4.     var actionContext = factory.GetService<IActionContextAccessor>().ActionContext;
  5.     return new UrlHelper(actionContext);
  6. });
  7. #endregion

注入到控制器

  1. private readonly IUrlHelper _urlHelper;
  2.  public PostController(IUnitOfWOrk UnitOfWOrk
  3.      , IPostRepository PostRepository
  4.      ,ILoggerFactory loggerFactory
  5.      ,IConfiguration configuration
  6.      ,IMapper mapper
  7.      , IUrlHelper urlHelper
  8.      )
  9.  {
  10.      this._PostRepository = PostRepository;
  11.      this._unitOfWork = UnitOfWOrk;
  12.      this._configuration = configuration;
  13.      this._mapper = mapper;
  14.      this._urlHelper = urlHelper;
  15.      this._Logger = loggerFactory.CreateLogger("AiDaSiBlog.API.Controllers.PostController");
  16.  }

生成前后页Url

  1.  private string CreatePostUri(PostParameters parameters,PaginationResourceUriType uriType)
  2.  {
  3.      switch (uriType)
  4.      {
  5.          case PaginationResourceUriType.PreviousPage:
  6.              var preiousParameters = new
  7.              {
  8.                  pagesize = parameters.PageSize,
  9.                  pageIndex = parameters.PageIndex-1,
  10.                   orderBy= parameters.OrderBy,
  11.                  fields = parameters.Fields
  12.              };
  13.              return _urlHelper.Link("GetPosts", preiousParameters);
  14.          case PaginationResourceUriType.NextPage:
  15.              var nextParameters = new
  16.              {
  17.                  pagesize = parameters.PageSize,
  18.                  pageIndex = parameters.PageIndex + 1,
  19.                  orderBy = parameters.OrderBy,
  20.                  fields = parameters.Fields
  21.              };
  22.              return _urlHelper.Link("GetPosts", nextParameters);
  23.          default:
  24.              var currentParameters = new
  25.              {
  26.                  pagesize = parameters.PageSize,
  27.                  pageIndex = parameters.PageIndex - 1,
  28.                  orderBy = parameters.OrderBy,
  29.                  fields = parameters.Fields
  30.              };
  31.              return _urlHelper.Link("GetPosts", currentParameters);
  32.      }
  33.  }

控制器代码修改一下

  1.  [HttpGet]
  2.  public async Task<IActionResult> Get(PostParameters postParameters)
  3.  {
  4.      var posts = await _PostRepository.GetAllPosts(postParameters);
  5.      var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(posts);
  6.      //判断上一页
  7.      var previousPageLink = posts.HasPrevious ? CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null;
  8.      //判断下一页
  9.      var nextPageLink = posts.HasNext ? CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;
  10.      var metta = new {
  11.          Pagesize = posts.PageSize,
  12.          PageIndex = posts.PageIndex,
  13.          TotalItemsCount = posts.TotalItemsCount,
  14.          PageCount = posts.PageCount,
  15.          PreviousPageLink=previousPageLink,
  16.          NextPageLink = nextPageLink
  17.      };
  18.      //标准化
  19.      Response.Headers.Add("x-Pagination", JsonConvert.SerializeObject(metta,new JsonSerializerSettings()
  20.      {
  21.          //Json输出格式小写
  22.          ContractResolver = new CamelCasePropertyNamesContractResolver()
  23.      }));
  24.      return Ok(postResources);
  25.  }

结果(数据都一样就不展示了):


4.搜索

修改PostParameters.cs类,添加Title字段

  1. public class PostParametersQueryParameters
  2. {
  3.     public string Title { getset; }
  4. }

修改PostRepository.cs类中GetAllPosts方法(这里我用了等于,大家可以用包含)

  1. public async Task<PaginatedList<Post>> GetAllPosts(PostParameters postParameters)
  2. {
  3.     #region 翻页,排序,查询
  4.     var query = _myContext.Posts.AsQueryable();
  5.     if (!string.IsNullOrEmpty(postParameters.Title))
  6.     {
  7.         var title = postParameters.Title.ToLowerInvariant();
  8.         query = query.Where(x => x.Title.ToLowerInvariant() == title);
  9.     }
  10.     query = query.OrderBy(x => x.Id);
  11.     var count = await query.CountAsync();
  12.     #endregion
  13.     //return await _myContext.Posts.ToListAsync();
  14.     var data = await query
  15.         .Skip(postParameters.PageIndex * postParameters.PageSize)
  16.         .Take(postParameters.PageSize)
  17.         .ToListAsync();
  18.     return new PaginatedList<Post>(postParameters.PageIndex,postParameters.PageSize,count,data);
  19. }


5.排序

这里我们用到 System.Linq.Dynamic.Core 类库

安装:



欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

剑轩

2021/8/20 12:46:59

这......么.....长

尘叶心繁:@剑轩还有下集

2021/8/20 13:33:12 回复

这一世以无限游戏为使命!
排名
2
文章
634
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术