1. 程式人生 > >Lind.DDD.Paging分頁模組介紹

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>

感謝各位的耐心閱讀!

回到目錄