ASP.NET分頁(yè)管理器的設(shè)計(jì)及實(shí)現(xiàn)
在DataGrid的web版控件中提供了自動(dòng)分頁(yè)的功能,但是我從來(lái)沒(méi)用過(guò)它,因?yàn)樗鼘?shí)現(xiàn)的分頁(yè)只是一種假相。我們?yōu)槭裁葱枰猪?yè)?那是因?yàn)榉蠗l件的記錄可能很多,如果一次讀取所有的記錄,不僅延長(zhǎng)獲取數(shù)據(jù)的時(shí)間,而且也極度浪費(fèi)內(nèi)存。而分頁(yè)的存在的主要目的正是為了解決這兩個(gè)問(wèn)題(當(dāng)然,也不排除為了UI美觀的需要而使用分頁(yè)的)。而web版的DataGrid是怎樣實(shí)現(xiàn)分頁(yè)的了?它并沒(méi)有打算解決上述兩個(gè)問(wèn)題,而還是一次讀取所有的數(shù)據(jù),然后以分頁(yè)的樣子表現(xiàn)出來(lái)。這是對(duì)效率和內(nèi)存的極大損害!
于是我自己實(shí)現(xiàn)了ASP.NET分頁(yè)管理器IPaginationManager ,IPaginationManager 每次從數(shù)據(jù)庫(kù)中讀取指定的任意一頁(yè),并且可以緩存指定數(shù)量的page。這個(gè)分頁(yè)管理器的主要特點(diǎn)是:
(1)支持隨機(jī)跳轉(zhuǎn)。這是通過(guò)嵌套Select語(yǔ)句實(shí)現(xiàn)的。
(2)支持緩存。通過(guò)EnterpriseServerBase.DataStructure.FixCacher進(jìn)行支持。
先來(lái)看看IPaginationManager接口的定義:
- public interface IPaginationManager
 - {
 - void Initialize(DataPaginationParas paras) ;
 - void Initialize(IDBAccesser accesser ,
 - int page_Size ,string whereStr ,string[]
 - fields) ;//如果選擇所有列,fields可傳null
 - DataTable GetPage(int index) ; //取出第index頁(yè)
 - DataTable CurrentPage() ;
 - DataTable PrePage() ;
 - DataTable NextPage() ;
 - int PageCount{get ;}
 - int CacherSize{get; set; }
 - }
 
這個(gè)接口定義中,最主要的是GetPage()方法,實(shí)現(xiàn)了這個(gè)方法,其它的三個(gè)獲取頁(yè)面的方法CurrentPage、PrePage、NextPage也就非常容易了。另外,CacherSize屬性可以讓我們指定緩存頁(yè)面的數(shù)量。如果不需要緩存,則設(shè)置其值<=0,如果需要無(wú)限緩存,則值為Int.MaxValue。
IPaginationManager接口中的第二個(gè)Initialize方法,你不要關(guān)心,它是給XCodeFactory生成的數(shù)據(jù)層使用了,我們來(lái)看看第一個(gè)Initialize方法的參數(shù)類型DataPaginationParas的定義:
- public class DataPaginationParas
 - {
 - public int PageSize = 10 ;
 - public string[] Fields = {"*"};
 - //要搜索出的列,"*"表示所有列
 - public string ConnectString ;
 - public string TableName ;
 - public string WhereStr ;
 - //搜索條件的where字句
 - public DataPaginationParas
 - (string connStr ,string tableName ,
 - string whereStr)
 - {
 - this.ConnectString = connStr ;
 - this.TableName = tableName ;
 - this.WhereStr = whereStr ;
 - }
 - #region GetFiedString
 - public string GetFiedString()
 - {
 - if(this.Fields == null)
 - {
 - this.Fields = new string[] {"*"} ;
 - }
 - string fieldStrs = "" ;
 - for(int i=0 ;i
 - {
 - fieldStrs += " " + this.Fields[i] ;
 - if(i != (this.Fields.Length -1))
 - {
 - fieldStrs += " , " ;
 - }
 - else
 - {
 - fieldStrs += " " ;
 - }
 - }
 - return fieldStrs ;
 - }
 - #endregion
 - }
 
DataPaginationParas.GetFiedString用于把要搜索的列形成字符串以便嵌入到SQL語(yǔ)句中。DataPaginationParas中的其它字段的意思都很明顯。
現(xiàn)在來(lái)看看ASP.NET分頁(yè)管理器的實(shí)現(xiàn)了:
- public class PaginationManager :IPaginationManager
 - {
 - private DataPaginationParas theParas ;
 - private IADOBase adoBase ;
 - private DataTable curPage = null ;
 - private int itemCount = 0 ;
 - private int pageCount = -1 ;
 - private int curPageIndex = -1 ;
 - private FixCacher fixCacher = null ;
 - private string fieldStrs = "" ;
 - ///
 - /// cacheSize 小于等于0 -- 表示不緩存 ,
 - Int.MaxValue -- 緩存所有
 - ///
 - public PaginationManager(int cacheSize)
 - {
 - if(cacheSize == int.MaxValue)
 - {
 - this.fixCacher = new FixCacher() ;
 - }
 - else if(cacheSize >0)
 - {
 - this.fixCacher = new FixCacher(cacheSize) ;
 - }
 - else
 - {
 - this.fixCacher = null ;
 - }
 - }
 - public PaginationManager()
 - {}
 - #region IDataPaginationManager 成員
 - public int CacherSize
 - {
 - get
 - {
 - if(this.fixCacher == null)
 - {
 - return 0 ;
 - }
 - return this.fixCacher.Size ;
 - }
 - set
 - {
 - if(this.fixCacher == null)
 - {
 - this.fixCacher = new FixCacher(value) ;
 - }
 - else
 - {
 - this.fixCacher.Size = value ;
 - }
 - }
 - }
 - public int PageCount
 - {
 - get
 - {
 - if(this.pageCount == -1)
 - {
 - string selCountStr = string.Format
 - ("Select count(*) from {0} {1}" ,this.theParas.
 - TableName ,this.theParas.WhereStr) ;
 - DataSet ds = this.adoBase.DoQuery(selCountStr) ;
 - this.itemCount = int.Parse(ds.Tables[0].
 - Rows[0][0].ToString()) ;
 - this.pageCount = this.itemCount/this.
 - theParas.PageSize ;
 - if((this.itemCount%this.theParas.PageSize > 0))
 - {
 - ++ this.pageCount ;
 - }
 - }
 - return this.pageCount ;
 - }
 - }
 - ///
 - /// GetPage 取出指定的一頁(yè)
 - ///
 - public DataTable GetPage(int index)
 - {
 - if(index == this.curPageIndex)
 - {
 - return this.curPage ;
 - }
 - if((index < 0) || (index > (this.PageCount-1)))
 - {
 - return null;
 - }
 - DataTable dt = this.GetCachedObject(index) ;
 - if(dt == null)
 - {
 - string selectStr = this.ConstrutSelectStr(index) ;
 - DataSet ds = this.adoBase.DoQuery(selectStr) ;
 - dt = ds.Tables[0] ;
 - this.CacheObject(index ,dt) ;
 - }
 - this.curPage = dt ;
 - this.curPageIndex = index ;
 - return this.curPage ;
 - }
 - private DataTable GetCachedObject(int index)
 - {
 - if(this.fixCacher == null)
 - {
 - return null ;
 - }
 - return (DataTable)this.fixCacher[index] ;
 - }
 - private void CacheObject(int index ,DataTable page)
 - {
 - if(this.fixCacher != null)
 - {
 - this.fixCacher.PutIn(index ,page) ;
 - }
 - }
 - public DataTable CurrentPage()
 - {
 - return this.curPage ;
 - }
 - public DataTable PrePage()
 - {
 - return this.GetPage((--this.curPageIndex)) ;
 - }
 - public DataTable NextPage()
 - {
 - return this.GetPage((++this.curPageIndex)) ;
 - }
 - private string ConstrutSelectStr(int pageIndex)
 - {
 - if(pageIndex == 0)
 - {
 - return string.Format("Select top {0} {1} from
 - {2} {3} ORDER BY ID" ,this.theParas.PageSize ,
 - this.fieldStrs ,this.theParas.TableName ,
 - this.theParas.WhereStr) ;
 - }
 - int innerCount = this.itemCount -
 - this.theParas.PageSize*pageIndex ;
 - string innerSelStr = string.Format("Select
 - top {0} {1} from {2} {3} ORDER BY ID DESC " ,
 - innerCount , this.fieldStrs ,this.theParas.
 - TableName ,this.theParas.WhereStr) ;
 - string outerSelStr = string.Format("Select top {0}
 - * from ({1}) DERIVEDTBL ORDER BY ID" ,this.
 - theParas.PageSize ,innerSelStr) ;
 - return outerSelStr ;
 - }
 - #region Initialize
 - public void Initialize(IDBAccesser accesser,
 - int page_Size, string whereStr, string[] fields)
 - {
 - this.theParas = new DataPaginationParas(accesser.
 - ConnectString ,accesser.DbTableName ,whereStr) ;
 - this.theParas.Fields = fields ;
 - this.theParas.PageSize = page_Size ;
 - this.fieldStrs = this.theParas.GetFiedString() ;
 - this.adoBase = new SqlADOBase(this.theParas.
 - ConnectString) ;
 - }
 - public void Initialize(DataPaginationParas paras)
 - {
 - this.theParas = paras ;
 - this.fieldStrs = this.theParas.GetFiedString() ;
 - this.adoBase = new SqlADOBase(this.theParas.
 - ConnectString) ;
 - }
 - #endregion
 - #endregion
 - }
 
解這個(gè)類的實(shí)現(xiàn),可以從GetPage(int index)方法入手,另外私有方法ConstrutSelectStr()的實(shí)現(xiàn)說(shuō)明了如何使用嵌套sql語(yǔ)句進(jìn)行隨機(jī)分頁(yè)搜索。
最后,關(guān)于分頁(yè)管理器,需要指出的是,搜索對(duì)應(yīng)的表必須有一個(gè)名為"ID"的主鍵--這是唯一的要求。另外,分頁(yè)管理器實(shí)現(xiàn)用到的數(shù)據(jù)訪問(wèn)低階封裝IADOBase定義于EnterpriseServerBase類庫(kù)中。
使用ASP.NET分頁(yè)管理器是很簡(jiǎn)單的,加上UI界面后,只要把返回的DataTable綁定到DataGrid就可以了。
【編輯推薦】















 
 
 
 
 
 
 