`
feipigwang
  • 浏览: 775251 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

实现你自己的分页管理器

 
阅读更多

在DataGrid的web版控件中提供了自动分页的功能,但是我从来没用过它,因为它实现的分页只是一种假相。我们为什么需要分页?那是因为符合条件的记录可能很多,如果一次读取所有的记录,不仅延长获取数据的时间,而且也极度浪费内存。而分页的存在的主要目的正是为了解决这两个问题(当然,也不排除为了UI美观的需要而使用分页的)。而web版的DataGrid是怎样实现分页的了?它并没有打算解决上述两个问题,而还是一次读取所有的数据,然后以分页的样子表现出来。这是对效率和内存的极大损害!
于是我自己写了一个分页管理器,关于它的描述和实现如下所示:

/**////<summary>
///IDataPaginationManager用于实现数据查询的分页操作。
///当表中的数据记录很多时,用Apdater一次读出所有的数据即耗费时间又浪费内存,这时就要用到分页了。
///DataPaginationManager每次从数据库中读取指定的一页,并且把历史页缓存在Stack中,这样,如果再次访问历史页,
///就不用再访问数据库了,直接从Stack中取出即可。
///
///作者:朱伟sky.zhuwei@163.com
///</summary>

publicinterfaceIDataPaginationManager
{
//complexIDName如"ID"或"sta.ID"(用于复合查询)
//selectStr中不允许包括GroupBy和OrderBy等字段
//voidInitialize(IDBAccesseraccesser,stringselectStr,stringcomplexID_Name);

intItemCount{get;}
intPageCount{get;}
intCurrentPageIndex{get;}
DataTableStartPage();
DataTableNextPage();
DataTablePrePage();
DataTableCurrentPage
{get;}
DataTableGetPage(
intindex);//只能随机访问曾经读取过的页

eventPageChangedCurrentPageIndexChanged;
}


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

publicclassDataPaginationManager:IDataPaginationManager
{
privatePaginationParascurParas=null;
privateIADOBaseadoBase=null;
privateintpageCount=0;
privateintitemCount=0;

privateDataTablecurrentPage=null;
privateintcurPageIndex=0;

//用Stack来存储历史页,以实现前一页操作
privateStackstatusStackForward=newStack();
privateStackstatusStackBackWard=newStack();
privateboolpreForward=true;//上一次是正向?

publiceventPageChangedCurrentPageIndexChanged;

IDataPagination成员#regionIDataPagination成员
publicDataPaginationManager(IDBAccesseraccesser,stringselectStr,stringcomplexID_Name,intpage_size)
{
this.curParas=newPaginationParas();
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();
}


publicDataPaginationManager(PaginationParasparas)
{
this.curParas=paras;
this.InitializeAdoBase(this.curParas.DbType,this.curParas.ConnectString);
this.pageCount=this.GetPageCount();
}


private#regionprivate
privatevoidInitializeAdoBase(DataBaseTypedbType,stringconnStr)
{
switch(dbType)
{
caseDataBaseType.SqlServer:
{
this.adoBase=newSqlADOBase(connStr);
break;
}

caseDataBaseType.Ole:
{
this.adoBase=newOleADOBase(connStr);
break;
}

default:
{
thrownewException("ThetargetDataBaseTypeisnotimplemented!");
}

}

}


privatestringCheckSelectString(stringselectStr)
{
if((selectStr==null)||(selectStr==""))
{
thrownewException("SelectStrisinvalid!");
}


stringstr=selectStr.ToLower();
if((str.IndexOf("orderby")!=-1)||(str.IndexOf("groupby")!=-1))
{
thrownewException("SelectStrCan'tcontain'orderby'or'groupby'!");
}


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


privatestringConstructSelectString(boolfirst,boolforward,PageStatuscurSta)
{
if(first)
{
returnthis.curParas.SelectString;
}



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


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


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


privateintGetPageCount()
{
stringstr=null;
intindex=this.curParas.SelectString.IndexOf("where");
if(-1==index)
{
str
=string.Format("SelectCount(*)from{0}",this.curParas.DBTableName);
}

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


DataSetds
=this.adoBase.DoQuery(str);

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


returnpageCount;
}


this.itemCount=0;
return0;
}

#endregion


PageCount,CurrentPageIndex,CurrentPage#regionPageCount,CurrentPageIndex,CurrentPage
publicintPageCount
{
get
{
returnthis.pageCount;
}

}


publicintItemCount
{
get
{
returnthis.itemCount;
}

}


publicintCurrentPageIndex
{
get
{
returnthis.curPageIndex;
}

}


publicDataTableCurrentPage
{
get
{
returnthis.currentPage;
}

}

#endregion


StartPage#regionStartPage
publicDataTableStartPage()
{
if(this.pageCount==0)
{
returnnull;
}


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

stringselect=this.ConstructSelectString(true,true,null);
DataSetds
=this.adoBase.DoQuery(select);

PageStatussta
=newPageStatus();
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);

returnthis.currentPage;
}

#endregion


NextPage#regionNextPage
publicDataTableNextPage()
{
if(this.curPageIndex>=this.pageCount-1)
{
returnnull;
}


if(this.statusStackBackWard.Count>0)
{
PageStatusstaRes
=(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);
}

}


returnthis.ReturnCurrentPage(staRes.curTable,true);
}


PageStatuscurSta
=(PageStatus)this.statusStackForward.Peek();
stringselect=this.ConstructSelectString(false,true,curSta);
DataSetds
=this.adoBase.DoQuery(select);

PageStatussta
=newPageStatus();
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);

returnthis.ReturnCurrentPage(sta.curTable,true);
}

#endregion


PrePage#regionPrePage
publicDataTablePrePage()
{
if(this.curPageIndex<1)
{
returnnull;
}


PageStatusoldSta
=(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);
}

}


returnthis.ReturnCurrentPage(oldSta.curTable,false);
}

#endregion


ReturnCurrentPage#regionReturnCurrentPage
privateDataTableReturnCurrentPage(DataTablecurPage,boolfoward)
{
if(curPage==null)
{
returnnull;
}


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

else
{
--this.curPageIndex;
}


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

returnthis.currentPage;
}

#endregion


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


intdistance=index-this.curPageIndex;

if(distance==0)
{
returnthis.currentPage;
}

elseif(distance>0)
{
for(inti=0;i<distance;i++)
{
this.NextPage();
}


returnthis.currentPage;
}

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


returnthis.currentPage;
}

}

#endregion


ActivePageIndexChanged#regionActivePageIndexChanged
privatevoidActivePageIndexChanged(intindex)
{
if(this.CurrentPageIndexChanged!=null)
{
this.CurrentPageIndexChanged(index);
}

}

#endregion


#endregion

}


publicclassPageStatus
{
publicstringcurIDValueEnd="";//本页最后一条记录ID
publicstringpreIDValueHead="";//上页第一条记录ID
publicDataTablecurTable=null;
}


publicclassPaginationParas
{
publicstringConnectString=null;
publicstringSelectString=null;
publicstringComplexIDName=null;
publicstringDBTableName=null;
publicintPageSize=0;
publicDataBaseTypeDbType=DataBaseType.SqlServer;
}


publicdelegatevoidPageChanged(intpageIndex);

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

stringselectStr="SelectID,Title,UploadUserName,UploadTime,Description,IsCasePic,CaseIDfromBinaryInformationDetail";
this.curPageMgr=DataEntrance.GetPaginationMgr(typeof(BinaryInformationDetail),selectStr,"ID",5);
DataTabledtStart
=this.curPageMgr.StartPage();
this.DataList1.DataSource=dtPic;
this.DataList1.DataBind();

否则,你需要通过DataPaginationManager的第二个构造函数来使用分页管理器。要提出的是,DataPaginationManager不能随机跳转到未访问过的页面(紧邻的下一页除外),这是由我们的实现方式(一次仅仅读取一页)决定的,我并不觉得随机跳转到任意页面是一种很必要的操作!

分享到:
评论

相关推荐

    java web 分页管理器

    Java Web分页管理器是一种用于处理大量数据分页显示的技术,尤其在与微软数据库如SQL Server配合使用时,能够高效地提升用户体验。在Web应用程序中,分页是必不可少的功能,尤其是在展示诸如用户列表、订单历史或者...

    操作系统 程实现请求分页存储管理页面Optimal、FIFO、LRU置换算法

    本实验旨在通过实际编程实现请求分页存储管理中的三种页面置换算法:最优置换算法(Optimal)、先进先出置换算法(FIFO)以及最近最少使用置换算法(LRU),帮助学生深入理解和掌握虚拟存储管理的核心概念和技术。...

    基本分段和分页管理系统实现

    在本文中,我们将深入探讨基本的分段和分页管理系统实现,这是操作系统中的核心概念。这两种方法都用于将进程的虚拟地址空间映射到物理内存中,以解决内存碎片问题并提高资源利用率。 首先,让我们了解一下分段内存...

    分页存储管理模拟C语言实现FIFO

    分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从0开始,如第0页、第1页等。相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame)...

    操作系统-基本分页存储管理(内有代码)

    分页存储管理的实现依赖于页表的数据结构,它记录了每个进程分配到的内存页的信息,以及内存页的物理地址。操作系统通过页表来实现虚拟地址到物理地址的映射。当进程运行时,如果需要访问某个内存位置,操作系统的...

    struts2.0实现的数据分页实现及实现分页步骤

    你需要创建一个Action类,比如`PaginationAction`,在这个类中实现分页逻辑。Action类通常包含获取数据的方法,如`loadData`,该方法将根据当前页码和每页大小计算SQL的LIMIT子句,并调用`DbPool`执行查询。 4. **...

    基本分页存储管理全.java

    基本分页存储管理全.java

    操作系统请求分页存储器管理C++代码实现

    2.能够模拟内存的分页式分配和回收过程,可查看内存分配位示图和进程页表; 3.可根据内存分配状态进行地址转换。 4.能够模拟基于虚拟存储器的内存分配和回收过程,可查看交换空间位示图和扩 展的页表; 5.在虚拟...

    java实现的一个分页程序

    2. **SQL分页查询**:在SQL中,不同的数据库管理系统(如MySQL, Oracle, SQL Server)有不同的语法来实现分页。例如,MySQL使用`LIMIT`和`OFFSET`,而Oracle可能使用`ROWNUM`。 3. **Page对象**:为了更好地封装...

    hbase分页查询实现.pdf

    这就使得开发者需要自己实现分页查询功能。本文将讲解如何使用Java语言实现HBase的分页查询。 知识点1:HBase的配置 在使用HBase之前,需要首先进行配置。配置包括设置ZooKeeper的Quorum和ClientPort等信息。在...

    SSH实现分页实例

    在这个"SSH实现分页实例"中,我们将深入探讨如何在SSH框架下实现数据的分页显示。 首先,Struts2作为MVC框架,负责处理HTTP请求并调度控制层逻辑。它通过Action类来封装业务逻辑,并通过配置ActionMapping定义请求...

    基本分页存储管理

    分页管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号。 3. 页表机制:在进程装入内存时,通过使用页表实现进程逻辑地址到物理地址的转换。页表机制是基本分页存储管理的...

    用recyclerview实现分页滑动,横向纵向分页

    在实现分页时,我们主要关注LayoutManager。 1. **纵向分页**: 在Android中,通常使用LinearLayoutManager实现纵向滚动。为了实现分页,我们可以监听RecyclerView的滑动事件,并在用户接近底部时加载下一页。这...

    先进先出实现分页管理的缺页调度

    "先进先出(FIFO)实现分页管理的缺页调度"是一种常见的页面替换算法。根据这个算法,当一个页面需要被换出时,会选择最早进入内存的页面进行替换,即最先进入主存的页面最先被替换出去。这种算法简单直观,但往往会...

    操作系统实验报告+源代码 基本分页存储管理

    通过这次实验,学生不仅加深了对基本分页存储管理原理的理解,还掌握了如何用编程语言实现这些概念。这个模拟程序可以作为理解和学习操作系统内存管理的基础,有助于进一步探讨更复杂的内存管理策略,如多级页表、页...

    操作系统实验分页管理

    通过实际操作,学生可以更直观地看到虚拟地址到物理地址转换的过程,理解请求分页管理的重要性和其实现机制。 总之,通过本次实验的学习,学生能够更加深入地理解操作系统内存管理的核心概念和技术细节。

    QT5分页组件,可以实现简单的数据分页

    `pagenavigator.cpp`、`pagenavigator.h`和`pagenavigator.ui`这三个文件是实现分页功能的关键文件。`.cpp`文件包含了C++代码,实现了分页组件的逻辑和交互;`.h`文件是头文件,定义了类及其成员函数,用于其他部分...

    java 真假分页,jsp servlet 实现的真分页与假分页

    在Java Web开发中,分页是常见的数据展示方式,它能有效地管理大量数据,提高用户体验。JSP(JavaServer Pages)和Servlet是Java Web开发中的关键组件,它们一起用于构建动态网页。本篇文章将深入探讨"真分页"和"假...

    Java实现真分页.自己领悟.

    使用自定义标签库实现分页的好处在于代码的可重用性和易维护性。开发者可以通过简单的标签语法在页面上插入分页组件,而复杂的逻辑则封装在后台Java代码中。例如,`&lt;pagetag:pagination&gt;`标签可能包含如`pageNo`、`...

    基于GridView和ActivityGroup实现的TAB分页

    在Tab分页的实现中,每个Tab下的内容可能由不同的Activity呈现,ActivityGroup可以帮助你在同一个父Activity下管理和切换这些子Activity,从而实现分页效果。然而,由于ActivityGroup存在一些问题,如内存泄漏、生命...

Global site tag (gtag.js) - Google Analytics