• Lind.DDD.Paging分页模块介绍


    回到目录

    分页组件网上有很多,MVC.Pager,JSPager等,通过实现方式大体分为前端分页和后端分页,前端分页是前台对list内存本地集合进行分页,缺点就是在大数据情况下,内存占用过高;后端分页就是UI把要返回的页号告诉后台,由后台组织数据并返回,这种方法就是我们经常看到的了;而根据后台集合种类又可以分类List和IQueryable,前者是本地集合,在返回数据时,直接把第几页共几条的集合返回;IQueryable是预查询集合,它是Linq的产物,在很多地里它不通用,除非你的ORM框架支持Linq,否则建议用List本地集合,一般来说,分页的本地集合会在底层提供一些方法,它的参数一般包含了pageIndex和pageSize,下面可以看一下大叔针对mongodb制定的分页规范

          /// <summary>
            /// MongoDB集成的查询方法,大数据情况下,有分页时使用这个方法
            /// </summary>
            /// <typeparam name="U">匿名对象,用来为条件赋值</typeparam>
            /// <param name="template">条件对象</param>
            /// <param name="limit"></param>
            /// <param name="skip"></param>
            /// <returns></returns>
            PagedResult<TEntity> GetModel<U>(U template, int pageIndex, int pageSize);

    而在Linq的底层,可以直接返回IQueryable集合,而在业务层进行返回Lind.DDD.Paging的分页集合即可,这块比较方便,今天主要说的是Linq下的分页方法

         /// <summary>
            /// 拿到可查询结果集(Linq)
            /// </summary>
            /// <returns></returns>
            System.Linq.IQueryable<TEntity> GetModel();

    LINQ环境下大叔分页的介绍

    分页基类

     public abstract class PageListBase<T> : 
            List<T>, 
            IEnumerable<T>, 
            IPagedList //繼承List<T>可以使用它的内部方法,如AddRange,Skip,Take等
        {
            /// <summary>
            /// 初始化分页
            /// </summary>
            public PageListBase()
            {
                this.AddParameters = new NameValueCollection();
                this.PageSize = 10;
            }
    
            /// <summary>
            /// 总页数
            /// </summary>
            public int TotalPages { get; set; }
    
            /// <summary>
            /// 总记录数
            /// </summary>
            public int TotalCount { get; set; }
    
            /// <summary>
            /// 当前页
            /// </summary>
            public int PageIndex { get; set; }
    
            /// <summary>
            /// 每页显示多少条记录
            /// </summary>
            public int PageSize { get; set; }
    
            /// <summary>
            /// 是否有上一页
            /// </summary>
            public bool IsPreviousPage { get { return (PageIndex > 0); } }
    
            /// <summary>
            /// 是否有下一页
            /// </summary>
            public bool IsNextPage { get { return (PageIndex * PageSize) <= TotalCount; } }
    
            /// <summary>
            /// 分页参数
            /// </summary>
            public NameValueCollection AddParameters { get; set; }
        }

    对于分页我们提供了传统分页和微博式(加载更多)分页,它们有自己的返回对象,看一下代码

        /// <summary>
        /// 分页通用类(传统分页)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class PagedList<T> : PageListBase<T>
        {
            public PagedList()
                : this(null, 0, 0)
            {
            }
            /// <summary>
            /// 数据源为IQueryable的范型
            /// </summary>
            /// <param name="source">数据源</param>
            /// <param name="index">当前页</param>
            /// <param name="pageSize">每页显示多少条记录</param>
            public PagedList(IQueryable<T> source, int index, int pageSize)
            {
                if (source != null) //判断传过来的实体集是否为空
                {
                    int total = source.Count();
                    this.TotalCount = total;
                    this.TotalPages = total / pageSize;
    
                    if (total % pageSize > 0)
                        TotalPages++;
    
                    this.PageSize = pageSize;
                    if (index > this.TotalPages)
                    {
                        index = this.TotalPages;
                    }
                    if (index < 1)
                    {
                        index = 1;
                    }
                    this.PageIndex = index;
                    this.AddRange(source.Skip((index - 1) * pageSize).Take(pageSize).ToList()); //Skip是跳到第几页,Take返回多少条
                }
            }
        }

    微博式分页主要是在原有数据基础上,进行追加数据,这在Linq里相当于一个Skip(0)加Take(PageIndex*PageSize)的动作,呵呵

        /// <summary>
        /// 以追加的方式,显示内容,即从第1页开始显示N条记录
        /// </summary>
        /// <typeparam name="T"></typeparam>
         public class PageListAppend<T> : PageListBase<T>
        {
            /// <summary>
            /// 数据源为IQueryable的范型
            /// </summary>
            /// <param name="source">数据源</param>
            /// <param name="index">当前页</param>
            /// <param name="pageSize">每页显示多少条记录</param>
            public PageListAppend(IQueryable<T> source, int index, int pageSize)
            {
                if (source != null) //判断传过来的实体集是否为空
                {
                    int total = source.Count();
                    this.TotalCount = total;
                    this.TotalPages = total / pageSize;
    
                    if (total % pageSize > 0)
                        TotalPages++;
    
                    this.PageSize = pageSize;
                    if (index > this.TotalPages)
                    {
                        index = this.TotalPages;
                    }
                    if (index < 1)
                    {
                        index = 1;
                    }
                    this.PageIndex = index;
                    this.AddRange(source.Skip(0).Take(index * pageSize).ToList()); //Skip是跳到第几页,Take返回多少条
                }
            }
        }

    有一点要特别注意一下,在LINQ分页时,我们看到被传入的集合一定是IQueryable的,如果是本地IList集合,那就失去了分页的意义,它相当于把所有数据加载到内存,然后再分页了。

    有了数据的返回,下面再来看一下前台页面的组织,我们也封装了一个PagerHelper的方法,当然你也可以在分部页上进行设计,这都是可以的。

    我们在前台调用时为大家封装了ajax分页,传统分页和微博分页等,直接在view上调用即可,当然如果你在前台对样式要求比较严格,也可以自己设计分布页来实现

    @{
        //分页灵活视图,根据自己项目的需要,去重写它
        Layout = null;
        var route = Request.RequestContext.RouteData.Values;
        var controller = route["controller"].ToString();
        var action = route["action"].ToString();
        var currentPage = int.Parse((route["page"] ?? Request.QueryString["page"] ?? "1").ToString());
    
        var pageCount = int.Parse((route["pageCount"] ?? Request.QueryString["pageCount"] ?? "1").ToString());
        if (currentPage < 1)
        {
            currentPage = 1;
        }
        if (currentPage > pageCount)
        {
            currentPage = pageCount;
        }
    }
    <div>
        <span>@Html.ActionLink("首页", action, controller, new { page = 1 })</span>
        <span>@Html.ActionLink("上一页", "Index", new { page = currentPage - 1 })</span>
        <span>@Html.ActionLink("下一页", "Index", new { page = currentPage + 1 })</span>
        <span>@Html.ActionLink("尾页", "Index", new { page = pageCount })</span>
        <span>@currentPage/@pageCount</span>
    </div>

    感谢各位的耐心阅读!

    回到目录

  • 相关阅读:
    Eureka的使用
    自定义类加载器
    继承
    Active Objects模式
    Future设计模式
    mysql备份与还原
    多生产者多消费者(第一种方式),基于synchronized,wait,notifyAll
    自己实现阻塞队列(基于数组)
    linux定时任务每隔5分钟向文本追加一行
    自己实现CountDownLatch
  • 原文地址:https://www.cnblogs.com/lori/p/5178978.html
Copyright © 2020-2023  润新知