首页 > 编程 > .NET > 正文

利用ASP.NET实现分页管理器

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

  于是我自己实现了分页管理器ipaginationmanager ,ipaginationmanager 每次从数据库中读取指定的任意一页,并且可以缓存指定数量的page。这个分页管理器的主要特点是:

  (1)支持随机跳转。这是通过嵌套select语句实现的。

  (2)支持缓存。通过enterpriseserverbase.datastructure.fixcacher进行支持。

  先来看看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页
 datatable currentpage() ;
 datatable prepage() ;
 datatable nextpage() ;

 int pagecount{get ;}
 int cachersize{get; set; }
}
  这个接口定义中,最主要的是getpage()方法,实现了这个方法,其它的三个获取页面的方法currentpage、prepage、nextpage也就非常容易了。另外,cachersize属性可以让我们指定缓存页面的数量。如果不需要缓存,则设置其值<=0,如果需要无限缓存,则值为int.maxvalue。

  ipaginationmanager接口中的第二个initialize方法,你不要关心,它是给xcodefactory生成的数据层使用了,我们来看看第一个initialize方法的参数类型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 = newstring[] {"*"} ;
  }

  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语句中。datapaginationparas中的其它字段的意思都很明显。

  现在来看看分页管理器的实现了:

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 取出指定的一页
 ///

 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
}
  了解这个类的实现,可以从getpage(int index)方法入手,另外私有方法construtselectstr()的实现说明了如何使用嵌套sql语句进行随机分页搜索。

  最后,关于分页管理器,需要指出的是,搜索对应的表必须有一个名为"id"的主键--这是唯一的要求。另外,分页管理器实现用到的数据访问低阶封装iadobase定义于enterpriseserverbase类库中。

  使用分页管理器是很简单的,加上ui界面后,只要把返回的datatable绑定到datagrid就可以了。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表