zoukankan      html  css  js  c++  java
  • 实现你自己的分页管理器

    在DataGrid的web版控件中提供了自动分页的功能,但是我从来没用过它,因为它实现的分页只是一种假相。我们为什么需要分页?那是因为符合条件的记录可能很多,如果一次读取所有的记录,不仅延长获取数据的时间,而且也极度浪费内存。而分页的存在的主要目的正是为了解决这两个问题(当然,也不排除为了UI美观的需要而使用分页的)。而web版的DataGrid是怎样实现分页的了?它并没有打算解决上述两个问题,而还是一次读取所有的数据,然后以分页的样子表现出来。这是对效率和内存的极大损害!
            于是我自己写了一个分页管理器,关于它的描述和实现如下所示:
    **///<summary>
        
    /// IDataPaginationManager 用于实现数据查询的分页操作。
        
    /// 当表中的数据记录很多时,用Apdater一次读出所有的数据即耗费时间又浪费内存,这时就要用到分页了。
        
    /// DataPaginationManager每次从数据库中读取指定的一页,并且把历史页缓存在Stack中,这样,如果再次访问历史页,
        
    /// 就不用再访问数据库了,直接从Stack中取出即可。
        
    /// 
        
    /// 作者:朱伟 sky.zhuwei@163.com 
        
    /// </summary>

        public interface IDataPaginationManager
        
    {
            
    //complexIDName 如"ID"或"sta.ID"(用于复合查询)
            
    //selectStr 中不允许包括Group By 和 Order By 等字段
            
    //void Initialize(IDBAccesser accesser ,string selectStr ,string complexID_Name) ; 

            
    int       ItemCount{get ;}
            
    int          PageCount {get ;}
            
    int          CurrentPageIndex{get ;}
            DataTable StartPage() ;
            DataTable NextPage() ;
            DataTable PrePage()  ;
            DataTable CurrentPage 
    {get ;}
            DataTable GetPage(
    int index) ; //只能随机访问曾经读取过的页

            
    event PageChanged CurrentPageIndexChanged ;
        }


        
    /**//// <summary>
        
    /// DataPagination 是IDataPagination的默认实现。遵守SkyDataAccess协议--有一个表示唯一索引的字段"ID"
        
    /// </summary>

        public class DataPaginationManager : IDataPaginationManager
        
    {
            
    private PaginationParas curParas = null ;
            
    private IADOBase adoBase         = null ;
            
    private int pageCount            = 0 ;    
            
    private int itemCount            = 0 ;

            
    private DataTable currentPage    = null ;
            
    private int curPageIndex         = 0 ;                    

            
    //用Stack来存储历史页,以实现前一页操作
            private Stack statusStackForward  = new Stack() ;
            
    private Stack statusStackBackWard = new Stack() ;
            
    private bool preForward = true ;//上一次是正向?

            
    public  event PageChanged CurrentPageIndexChanged ;        

            IDataPagination 成员
    #region IDataPagination 成员
            
    public DataPaginationManager(IDBAccesser accesser ,string selectStr ,string complexID_Name ,int page_size)
            
    {            
                
    this.curParas = new PaginationParas() ;            
                
    this.curParas.ComplexIDName = complexID_Name ;            
                
    this.curParas.PageSize = page_size ;
                
    this.curParas.SelectString = this.CheckSelectString(selectStr) ;    
                
    this.curParas.ConnectString = accesser.ConnectString ;
                
    this.curParas.DbType        = accesser.DataBaseType ;
                
    this.curParas.DBTableName   = accesser.DbTableName  ;

                
    this.InitializeAdoBase(accesser.DataBaseType ,accesser.ConnectString) ;            
                
    this.pageCount = this.GetPageCount() ;
            }


            
    public DataPaginationManager(PaginationParas paras)
            
    {
                
    this.curParas = paras ;
                
    this.InitializeAdoBase(this.curParas.DbType ,this.curParas.ConnectString) ;            
                
    this.pageCount = this.GetPageCount() ;
            }


            
    private#region private
            
    private void InitializeAdoBase(DataBaseType dbType ,string connStr)
            
    {
                
    switch(dbType)
                
    {
                    
    case DataBaseType.SqlServer :
                    
    {
                        
    this.adoBase = new SqlADOBase(connStr) ;
                        
    break ;
                    }

                    
    case DataBaseType.Ole :
                    
    {
                        
    this.adoBase = new OleADOBase(connStr) ;
                        
    break ;
                    }

                    
    default:
                    
    {
                        
    throw new Exception("The target DataBaseType is not implemented !")  ;
                    }

                }

            }


            
    private string CheckSelectString(string selectStr)
            
    {
                
    if((selectStr == null|| (selectStr == ""))
                
    {
                    
    throw new Exception("SelectStr is invalid !")  ;
                }
                

                
    string str = selectStr.ToLower() ;
                
    if((str.IndexOf("order by"!= -1|| (str.IndexOf("group by"!= -1))
                
    {
                    
    throw new Exception("SelectStr Can't contain 'order by' or 'group by' !")  ;
                }
        

                selectStr 
    = selectStr.ToLower() ;
                
    string ss = string.Format("select top {0} " ,this.curParas.PageSize) ;
                
    return selectStr.Replace("select" ,ss );
            }


            
    private string ConstructSelectString(bool first ,bool forward ,PageStatus curSta)
            
    {
                
    if(first)
                
    {                
                    
    return this.curParas.SelectString ;
                }



                
    string comp = " >= " ;
                
    string curIDValue = curSta.preIDValueHead ;
                
    if(forward)
                
    {
                    comp 
    = " > " ;
                    curIDValue 
    = curSta.curIDValueEnd ;
                }
                

                
    if(-1 == this.curParas.SelectString.IndexOf("where"))
                
    {
                    
    return this.curParas.SelectString + string.Format(" where {0} {1} '{2}'" ,this.curParas.ComplexIDName ,comp ,curIDValue) ;
                }

                
                
    return this.curParas.SelectString + string.Format(" and {0} {1} '{2}'" ,this.curParas.ComplexIDName ,comp ,curIDValue) ;            
            }


            
    private int GetPageCount()
            
    {
                
    string str = null ;
                
    int index = this.curParas.SelectString.IndexOf("where") ;
                
    if(-1 == index)
                
    {
                    str 
    = string.Format("Select Count(*) from {0}" ,this.curParas.DBTableName) ;
                }

                
    else
                
    {
                    
    string whereStr = this.curParas.SelectString.Substring(index) ;
                    str 
    = string.Format("Select Count(*) from {0} {1}" ,this.curParas.DBTableName ,whereStr) ;                    
                }


                DataSet ds 
    = this.adoBase.DoQuery(str) ;
                
                
    if(ds.Tables[0].Rows.Count != 0)
                
    {
                    
    int num = int.Parse(ds.Tables[0].Rows[0][0].ToString()) ;
                    
    this.itemCount = num ;
                    
    int pageCount = num/this.curParas.PageSize ;
                    
    if(num%this.curParas.PageSize > 0)
                    
    {
                        pageCount 
    += 1 ;
                    }


                    
    return pageCount ;
                }


                
    this.itemCount = 0 ;
                
    return 0 ;
            }

            
    #endregion
            

            PageCount ,CurrentPageIndex ,CurrentPage
    #region PageCount ,CurrentPageIndex ,CurrentPage
            
    public int PageCount
            
    {
                
    get
                
    {
                    
    return this.pageCount ;
                }

            }


            
    public int ItemCount
            
    {
                
    get
                
    {
                    
    return this.itemCount ;
                }

            }


            
    public int CurrentPageIndex
            
    {
                
    get
                
    {
                    
    return this.curPageIndex ;
                }

            }


            
    public DataTable CurrentPage
            
    {
                
    get
                
    {
                    
    return this.currentPage ;
                }

            }

            
    #endregion


            StartPage
    #region StartPage
            
    public DataTable StartPage()
            
    {
                
    if(this.pageCount == 0)
                
    {
                    
    return null ;
                }


                
    this.statusStackBackWard.Clear() ;
                
    this.statusStackForward.Clear() ;

                
    string select = this.ConstructSelectString(true ,true ,null) ;
                DataSet ds 
    = this.adoBase.DoQuery(select) ;

                PageStatus sta 
    = new PageStatus() ;
                sta.curIDValueEnd  
    = ds.Tables[0].Rows[ds.Tables[0].Rows.Count-1]["ID"].ToString() ;
                sta.preIDValueHead 
    = ds.Tables[0].Rows[0]["ID"].ToString() ;
                sta.curTable 
    = ds.Tables[0] ;
                
    this.statusStackForward.Push(sta) ;

                
    this.curPageIndex   = 0 ;
                
    this.currentPage    = sta.curTable ;
                
    this.ActivePageIndexChanged(this.curPageIndex) ;

                
    return this.currentPage ;
            }

            
    #endregion


            NextPage
    #region NextPage
            
    public DataTable NextPage()
            
    {
                
    if(this.curPageIndex >= this.pageCount-1)
                
    {
                    
    return null ;
                }


                
    if(this.statusStackBackWard.Count >0)
                
    {                
                    PageStatus staRes 
    = (PageStatus)this.statusStackBackWard.Pop() ;
                    
    this.statusStackForward.Push(staRes) ;
                    
    if(! this.preForward)
                    
    {
                        
    if(this.statusStackBackWard.Count > 0)
                        
    {
                            staRes 
    = (PageStatus)this.statusStackBackWard.Pop() ;
                            
    this.statusStackForward.Push(staRes) ;
                        }

                    }

                    
                    
    return this.ReturnCurrentPage(staRes.curTable ,true) ;
                }


                PageStatus curSta 
    = (PageStatus)this.statusStackForward.Peek() ;    
                
    string select = this.ConstructSelectString(false ,true ,curSta) ;
                DataSet ds 
    = this.adoBase.DoQuery(select) ;            

                PageStatus sta 
    = new PageStatus() ;
                sta.curIDValueEnd  
    = ds.Tables[0].Rows[ds.Tables[0].Rows.Count-1]["ID"].ToString() ;
                sta.preIDValueHead 
    = curSta.curTable.Rows[0]["ID"].ToString() ;
                sta.curTable 
    = ds.Tables[0] ;
                
    this.statusStackForward.Push(sta) ;            

                
    return this.ReturnCurrentPage(sta.curTable ,true) ;
            }

            
    #endregion


            PrePage
    #region PrePage
            
    public DataTable PrePage()
            
    {
                
    if(this.curPageIndex < 1)
                
    {
                    
    return null ;
                }


                PageStatus oldSta 
    = (PageStatus)this.statusStackForward.Pop() ;    
                
    this.statusStackBackWard.Push(oldSta) ;

                
    if(this.preForward)
                
    {
                    
    if(this.statusStackForward.Count > 0)
                    
    {
                        oldSta 
    = (PageStatus)this.statusStackForward.Pop() ;    
                        
    this.statusStackBackWard.Push(oldSta) ;
                    }

                }
                

                
    return this.ReturnCurrentPage(oldSta.curTable ,false) ;
            }

            
    #endregion


            ReturnCurrentPage
    #region ReturnCurrentPage
            
    private DataTable ReturnCurrentPage(DataTable curPage ,bool foward)
            
    {
                
    if(curPage == null)
                
    {
                    
    return null ;
                }


                
    if(foward)
                
    {
                    
    ++ this.curPageIndex ;            
                }

                
    else
                
    {
                    
    -- this.curPageIndex ;    
                }


                
    this.preForward = foward ;
                
    this.currentPage = curPage ;
                
    this.ActivePageIndexChanged(this.curPageIndex) ;

                
    return this.currentPage ;
            }

            
    #endregion


            GetPage
    #region GetPage
            
    //如果历史记录中有对应的page,则返回它,否则返回null
            public DataTable GetPage(int index)
            
    {
                
    if(index > (this.statusStackBackWard.Count + this.statusStackForward.Count -1|| index < 0)
                
    {
                    
    return null ;
                }


                
    int distance = index - this.curPageIndex ;

                
    if(distance == 0)
                
    {
                    
    return this.currentPage ;
                }
                
                
    else if(distance > 0)
                
    {
                    
    for(int i=0 ;i<distance ;i++)
                    
    {
                        
    this.NextPage() ;
                    }


                    
    return this.currentPage ;
                }

                
    else
                
    {
                    
    for(int i=distance ;i<0 ;i++)
                    
    {
                        
    this.PrePage() ;
                    }


                    
    return this.currentPage ;
                }
                            
            }

            
    #endregion


            ActivePageIndexChanged
    #region ActivePageIndexChanged
            
    private void ActivePageIndexChanged(int index)
            
    {
                
    if(this.CurrentPageIndexChanged != null)
                
    {
                    
    this.CurrentPageIndexChanged(index) ;
                }

            }

            
    #endregion


            
    #endregion

        }


        
    public class PageStatus
        
    {
            
    public string     curIDValueEnd    = "" ; //本页最后一条记录ID
            public string     preIDValueHead   = "" ; //上页第一条记录ID
            public DataTable  curTable = null ;
        }


        
    public class PaginationParas
        
    {
            
    public string ConnectString = null ;
            
    public string SelectString  = null ;
            
    public string ComplexIDName = null ;    
            
    public string DBTableName   = null ;
            
    public int    PageSize      = 0 ;
            
    public DataBaseType  DbType = DataBaseType.SqlServer ;
        }


        
    public delegate void PageChanged(int pageIndex) ;

    如果你使用XCodeFactory生成的数据层代码,可以像下面这样使用分页管理器:

    string selectStr = "Select ID ,Title , UploadUserName ,UploadTime ,Description ,IsCasePic ,CaseID from BinaryInformationDetail  "  ;            
                
    this.curPageMgr = DataEntrance.GetPaginationMgr(typeof(BinaryInformationDetail) ,selectStr ,"ID" ,5) ;            
                DataTable dtStart 
    = this.curPageMgr.StartPage() ;            
                    
    this.DataList1.DataSource = dtPic ;
                    
    this.DataList1.DataBind() ;
     否则,你需要通过DataPaginationManager的第二个构造函数来使用分页管理器。要提出的是,DataPaginationManager不能随机跳转到未访问过的页面(紧邻的下一页除外),这是由我们的实现方式(一次仅仅读取一页)决定的,我并不觉得随机跳转到任意页面是一种很必要的操作!
  • 相关阅读:
    理解maven命令package、install、deploy的联系与区别
    Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
    Spring boot 外部资源配置
    配置spring boot 内置tomcat的accessLog日志
    spring使用@Value标签读取.properties文件的中文乱码问题的解决
    使用Lombok简化你的代码
    统计mysql数据库中数据表/字段等数量的sql
    Kettle
    Python内置函数(39)——locals
    Python内置函数(38)——list
  • 原文地址:https://www.cnblogs.com/studio313/p/219298.html
Copyright © 2011-2022 走看看