zoukankan      html  css  js  c++  java
  • MongoDB学习笔记~为IMongoRepository接口添加分页取集合的方法

    回到目录

    对于数据分页,我们已经见的太多了,几乎每个列表页面都要用到分页,这已经成了一种定理了,在进行大数据展示时,如果不去分页,而直接把数据加载到内存,这简直是不可以去相向的,呵呵,在很多ORM工具中都对分页有了更好的支持,如LINQ里有大家熟悉的take和skip,而在MongoDB里也有这种概念,它使用limit和skip实现,这在大多数的Mongo客户端上都集成了这个功能,即帮助我们组合命令参数,并带我们把分页取数据的指令发到Mongo服务器去,实现分页技术!

    添加了分页后的IMongoRepository接口

            /// <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);
            /// <summary>
            /// MongoDB集成的查询方法,大数据情况下,有分页和排序时使用这个方法
            /// </summary>
            /// <typeparam name="U">匿名对象,用来为条件赋值</typeparam>
            /// <typeparam name="O">匿名对象,用来为排序赋值,NoRM.OrderBy枚举</typeparam>
            /// <param name="template">条件对象</param>
            /// <param name="orderby">排序对象</param>
            /// <param name="limit"></param>
            /// <param name="skip"></param>
            /// <returns></returns>
            PagedResult<TEntity> GetModel<U, O>(U template, O orderby, int pageIndex, int pageSize);

    看我是如何去实现它的,事实上是调用了Mongo客户端封装的Find<T, U, O>(this IMongoCollection<T> collection, U template, O orderby, int limit, int skip);方法

    实现的,我们来看一下代码

      public PagedResult<TEntity> GetModel<U, O>(U template, O orderby, int pageIndex, int pageSize)
            {
                var skip = (pageIndex - 1) * pageSize;
                var limit = pageSize;
                var recordCount = _table.Count();
                return new PagedResult<TEntity>(
                    recordCount,
                    (int)(recordCount + pageSize - 1) / pageSize,
                    pageSize,
                    pageIndex,
                    _table.Find(template, orderby, limit, skip).ToList());
            }

    代码主要实现的是分页和排序功能,其中template是查询条件,可以传入一个匿名对象,而orderby参数表示一个排序的匿名对象,把排序字段写到对象里即可,升序为1,降

    序为-1,也可以使用它定义好的枚举来赋值,下面我们为上面方法做一个重载,来针对不需要排序的需求

       public PagedResult<TEntity> GetModel<U>(U template, int pageIndex, int pageSize)
            {
                return GetModel(template, new { }, pageIndex, pageSize);
            }

    有了底层的方法,再来看它的返回值,如果是分页返回对象,那么一定要返回一个PagedResult泛型对象,这个对象主要向外部公开一个参数,如当前页的数据集,当前页号

    每面显示记录数,总页数和总的记录数及URL条件集合等。

        /// <summary>
        /// 分页结果对象,UI显示它,BLL为它赋值
        /// 陈晴阳开发,张占岭修改,添加了AddParameters属性,用来存储URL参数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class PagedResult<T> : IEnumerable<T>, ICollection<T>
        {
            #region Public Fields
            /// <summary>
            /// 获取一个当前类型的空值。
            /// </summary>
            public static readonly PagedResult<T> Empty = new PagedResult<T>(0, 0, 0, 0, null);
            #endregion
    
            #region Ctor
            /// <summary>
            /// 初始化一个新的<c>PagedResult{T}</c>类型的实例。
            /// </summary>
            public PagedResult()
            {
                Data = new List<T>();
                AddParameters = new NameValueCollection();
                PageSize = 10;
            }
            /// <summary>
            /// 初始化一个新的<c>PagedResult{T}</c>类型的实例。
            /// </summary>
            /// <param name="totalRecords">总记录数。</param>
            /// <param name="totalPages">页数。</param>
            /// <param name="pageSize">页面大小。</param>
            /// <param name="pageNumber">页码。</param>
            /// <param name="data">当前页面的数据。</param>
            public PagedResult(long totalRecords, int totalPages, int pageSize, int pageNumber, List<T> data)
            {
                this.TotalPages = totalPages;
                this.TotalRecords = totalRecords;
                this.PageSize = pageSize;
                this.PageIndex = pageNumber;
                this.Data = data;
            }
            #endregion
    
            #region Public Properties
            /// <summary>
            /// 获取或设置总记录数。
            /// </summary>
            public long TotalRecords { get; set; }
            /// <summary>
            /// 获取或设置页数。
            /// </summary>
            public int TotalPages { get; set; }
            /// <summary>
            /// 获取或设置页面大小。
            /// </summary>
            public int PageSize { get; set; }
            /// <summary>
            /// 获取或设置页码。
            /// </summary>
            public int PageIndex { get; set; }
            /// <summary>
            /// 获取或设置当前页面的数据。
            /// </summary>
            public List<T> Data { get; set; }
            /// <summary>
            /// 分页参数
            /// </summary>
            public NameValueCollection AddParameters { get; set; }
            #endregion
    
            #region Public Methods
            /// <summary>
            /// 确定指定的Object是否等于当前的Object。
            /// </summary>
            /// <param name="obj">要与当前对象进行比较的对象。</param>
            /// <returns>如果指定的Object与当前Object相等,则返回true,否则返回false。</returns>
            /// <remarks>有关此函数的更多信息,请参见:http://msdn.microsoft.com/zh-cn/library/system.object.equals/// </remarks>
            public override bool Equals(object obj)
            {
                if (ReferenceEquals(this, obj))
                    return true;
                if (obj == (object)null)
                    return false;
                var other = obj as PagedResult<T>;
                if (other == (object)null)
                    return false;
                return this.TotalPages == other.TotalPages &&
                    this.TotalRecords == other.TotalRecords &&
                    this.PageIndex == other.PageIndex &&
                    this.PageSize == other.PageSize &&
                    this.Data == other.Data;
            }
    
            /// <summary>
            /// 用作特定类型的哈希函数。
            /// </summary>
            /// <returns>当前Object的哈希代码。</returns>
            /// <remarks>有关此函数的更多信息,请参见:http://msdn.microsoft.com/zh-cn/library/system.object.gethashcode/// </remarks>
            public override int GetHashCode()
            {
                return this.TotalPages.GetHashCode() ^
                    this.TotalRecords.GetHashCode() ^
                    this.PageIndex.GetHashCode() ^
                    this.PageSize.GetHashCode();
            }
    
            /// <summary>
            /// 确定两个对象是否相等。
            /// </summary>
            /// <param name="a">待确定的第一个对象。</param>
            /// <param name="b">待确定的另一个对象。</param>
            /// <returns>如果两者相等,则返回true,否则返回false。</returns>
            public static bool operator ==(PagedResult<T> a, PagedResult<T> b)
            {
                if (ReferenceEquals(a, b))
                    return true;
                if ((object)a == null || (object)b == null)
                    return false;
                return a.Equals(b);
            }
    
            /// <summary>
            /// 确定两个对象是否不相等。
            /// </summary>
            /// <param name="a">待确定的第一个对象。</param>
            /// <param name="b">待确定的另一个对象。</param>
            /// <returns>如果两者不相等,则返回true,否则返回false。</returns>
            public static bool operator !=(PagedResult<T> a, PagedResult<T> b)
            {
                return !(a == b);
            }
            #endregion
    
            #region IEnumerable<T> Members
            /// <summary>
            /// 返回一个循环访问集合的枚举数。
            /// </summary>
            /// <returns>一个可用于循环访问集合的 IEnumerator 对象。</returns>
            public IEnumerator<T> GetEnumerator()
            {
                return Data.GetEnumerator();
            }
    
            #endregion
    
            #region IEnumerable Members
            /// <summary>
            /// 返回一个循环访问集合的枚举数。 (继承自 IEnumerable。)
            /// </summary>
            /// <returns>一个可用于循环访问集合的 IEnumerator 对象。</returns>
            IEnumerator IEnumerable.GetEnumerator()
            {
                return Data.GetEnumerator();
            }
    
            #endregion
    
            #region ICollection<T> Members
            /// <summary>
            /// 将某项添加到 ICollection{T} 中。
            /// </summary>
            /// <param name="item">要添加到 ICollection{T} 的对象。</param>
            public void Add(T item)
            {
                Data.Add(item);
            }
    
            /// <summary>
            /// 从 ICollection{T} 中移除所有项。
            /// </summary>
            public void Clear()
            {
                Data.Clear();
            }
    
            /// <summary>
            /// 确定 ICollection{T} 是否包含特定值。
            /// </summary>
            /// <param name="item">要在 ICollection{T} 中定位的对象。</param>
            /// <returns>如果在 ICollection{T} 中找到 item,则为 true;否则为 false。</returns>
            public bool Contains(T item)
            {
                return Data.Contains(item);
            }
    
            /// <summary>
            /// 从特定的 Array 索引开始,将 ICollection{T} 的元素复制到一个 Array 中。
            /// </summary>
            /// <param name="array">作为从 ICollection{T} 复制的元素的目标的一维 Array。 Array 必须具有从零开始的索引。</param>
            /// <param name="arrayIndex">array 中从零开始的索引,从此索引处开始进行复制。</param>
            public void CopyTo(T[] array, int arrayIndex)
            {
                Data.CopyTo(array, arrayIndex);
            }
    
            /// <summary>
            /// 获取 ICollection{T} 中包含的元素数。
            /// </summary>
            public int Count
            {
                get { return Data.Count; }
            }
    
            /// <summary>
            /// 获取一个值,该值指示 ICollection{T} 是否为只读。
            /// </summary>
            public bool IsReadOnly
            {
                get { return false; }
            }
    
            /// <summary>
            /// 从 ICollection{T} 中移除特定对象的第一个匹配项。
            /// </summary>
            /// <param name="item">要从 ICollection{T} 中移除的对象。</param>
            /// <returns>如果已从 ICollection{T} 中成功移除 item,则为 true;否则为 false。 如果在原始 ICollection{T} 中没有找到 item,该方法也会返回 false。 </returns>
            public bool Remove(T item)
            {
                return Data.Remove(item);
            }
    
            #endregion
        }

    有了底层方法和返回的对象,下面就是前台显示了,我们可以扩展一个PagerHelper,重新为它起个名字叫PagedResultHelper吧,把它的相关PagedList类型对象修改成PagedResult对象即可,代码如下

      /// <summary>
        /// 关于PagedResult对象的分页展示
        /// 作者:张占岭,花名:仓储大叔
        /// </summary>
        public static class PagedResultHelper
        {
    
            #region Ajax分页
            /// <summary>
            /// AJAX分页
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="html"></param>
            /// <param name="pagedList"></param>
            /// <param name="UpdateTargetId"></param>
            /// <returns></returns>
            public static MvcHtmlString AjaxPagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, string UpdateTargetId, bool isDisplayCompletePage)
            {
                var ui = new UIHelper(html.ViewContext.RequestContext.HttpContext.Request.Url.ToString(), UpdateTargetId, pagedList.AddParameters);
                if (!isDisplayCompletePage)
                    return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex, pagedList.PageSize, (int)pagedList.TotalRecords, false));
                else
                    return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex, pagedList.PageSize, (int)pagedList.TotalRecords));
            }
    
            public static MvcHtmlString AjaxPager<T>(this HtmlHelper html, PagedResult<T> pagedList, string UpdateTargetId)
            {
                return AjaxPagerResult<T>(html, pagedList, UpdateTargetId, true);
            }
            /// <summary>
            /// AJAX分页
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="html"></param>
            /// <param name="pagedList"></param>
            /// <param name="UpdateTargetId"></param>
            /// <param name="ActionName"></param>
            /// <param name="ControllerName"></param>
            /// <returns></returns>
            public static MvcHtmlString AjaxPagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, string UpdateTargetId, string ActionName, string ControllerName, bool isDisplayCompletePage, bool isTop)
            {
                var mvcUrl = new UrlHelper(html.ViewContext.RequestContext).Action(ActionName, ControllerName); //占岭修改
                var localUrl = string.Format(@"{0}://{1}", html.ViewContext.RequestContext.HttpContext.Request.Url.Scheme, html.ViewContext.RequestContext.HttpContext.Request.Url.Authority);
                var url = string.Format("{0}{1}{2}", localUrl, mvcUrl, html.ViewContext.RequestContext.HttpContext.Request.Url.Query);
                var ui = new UIHelper(url, UpdateTargetId, pagedList.AddParameters);
                return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex, pagedList.PageSize, (int)pagedList.TotalRecords, isDisplayCompletePage, false, isTop));
            }
            public static MvcHtmlString AjaxPagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, string UpdateTargetId, string ActionName, string ControllerName, bool isDisplayCompletePage)
            {
                return AjaxPagerResult<T>(html, pagedList, UpdateTargetId, ActionName, ControllerName, true, false);
            }
            /// <summary>
            /// ajax方式,MVC路由支持的分页
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="html"></param>
            /// <param name="pagedList"></param>
            /// <param name="UpdateTargetId"></param>
            /// <param name="ActionName"></param>
            /// <param name="ControllerName"></param>
            /// <returns></returns>
            public static MvcHtmlString AjaxPagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, string UpdateTargetId, string ActionName, string ControllerName)
            {
                var mvcUrl = new UrlHelper(html.ViewContext.RequestContext).Action(ActionName, ControllerName); //占岭修改
                var localUrl = string.Format(@"{0}://{1}", html.ViewContext.RequestContext.HttpContext.Request.Url.Scheme, html.ViewContext.RequestContext.HttpContext.Request.Url.Authority);
                var url = string.Format("{0}{1}{2}", localUrl, mvcUrl, html.ViewContext.RequestContext.HttpContext.Request.Url.Query);
                var ui = new UIHelper(url, UpdateTargetId, pagedList.AddParameters);
    
                return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex
                   , pagedList.PageSize
                   , (int)pagedList.TotalRecords
                   , 0
                   , new UrlHelper(html.ViewContext.RequestContext)
                   , html.ViewContext.RouteData.Values["action"].ToString()
                   , html.ViewContext.RouteData.Values["controller"].ToString(), true, false, null));
    
            }
           
            #endregion
    
            #region Html分页
            /// <summary>
            /// Html分页,不使用MVC路由
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="html"></param>
            /// <param name="pagedList"></param>
            /// <returns></returns>
            public static MvcHtmlString PagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList)
            {
                return PagerResult<T>(html, pagedList, false);
            }
            public static MvcHtmlString PagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, string className)
            {
                return PagerResult<T>(html, pagedList, false, className);
            }
            public static MvcHtmlString PagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, bool router, string className)
            {
                return PagerResult<T>(html, pagedList, router, true, className);
            }
            /// <summary>
            /// Html分页,router为true表示走MVC路由
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="html"></param>
            /// <param name="pagedList"></param>
            /// <param name="router">路由</param>
            /// <param name="className">CSS类名</param>
            /// <returns></returns>
            public static MvcHtmlString PagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, bool router, bool isCompleteDisplay, string className)
            {
                if (pagedList == null)
                    return null;
                UIHelper ui = new UIHelper(html.ViewContext.RequestContext.HttpContext.Request.Url.ToString(), pagedList.AddParameters);
                if (router)
                    return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex
                        , pagedList.PageSize
                        , (int)pagedList.TotalRecords
                        , 0
                        , new UrlHelper(html.ViewContext.RequestContext)
                        , html.ViewContext.RouteData.Values["action"].ToString()
                        , html.ViewContext.RouteData.Values["controller"].ToString(), isCompleteDisplay, false, className));
                return MvcHtmlString.Create(ui.GetPage(pagedList.PageIndex, pagedList.PageSize, (int)pagedList.TotalRecords, isCompleteDisplay, className));
            }
            public static MvcHtmlString PagerResult<T>(this HtmlHelper html, PagedResult<T> pagedList, bool router)
            {
                return PagerResult<T>(html, pagedList, router, null);
            }
            #endregion
    
        }

    这样,我们前台调用分页时,还是一句话就搞定了,呵呵!

    事实上,对于PagedResult我们也可以用在其它ORM工具上,因为一定的数据库和NoSql都开放了limit及skip等功能,大家可以放眼去看,放心去想,呵呵!

    回到目录

  • 相关阅读:
    jquery通过val()取不到textarea中的值
    form表单右边弹窗提示不能为空
    正则表达式
    layui表格的批量删除功能
    layui中table表格的操作列(删除,编辑)等按钮的操作
    layui动态渲染生成select的option值
    layui实现table表格的“关键字搜索”功能
    Python3基础 break while循环示例
    Python3基础 bool类型变量赋值
    Python3基础 assert 断言 确保程序的正确运行条件
  • 原文地址:https://www.cnblogs.com/lori/p/4418584.html
Copyright © 2011-2022 走看看