• 浅谈分页技术


    转自:http://www.cnblogs.com/dlwang2002/archive/2005/10/14/254971.html

    这几天看到几篇关于分页的文章,觉得有些东西可以分享一下。这里提供一些关于UI分页和数据库分页的一些解决方案。还有一些常用控件的使用方法概要

    通常一个查询语句如果得到的数据量过大或者为了UI美观考虑,就需要进行对这些数据进行分页显示。

    分页其实有两类,界面上分页和数据库分页。

    关于数据显示控件

    Repeater

      这个是最基本的数据集帮订显示控件。不支持分页

    DataList

      比上一个功能要复杂一点,但是也不支持分页

    GridView(DataGrid)

      支持分页,功能最强大。效率也是最低的一个。

    当然,也可以写自己的分页控件,或者包装一个现有的。

    数据库分页

      事实上,数据库分页依赖于具体数据库。每种数据库提供的语句不太一样,具体操作要根据具体的数据库才决定。

      比方说sql server :sql server数据分页 比较 http://www.cnblogs.com/dlwang2002/archive/2005/10/14/254971.html

      比方说oracle:它提供了一个RowNum列,所以分页算法很容易实现。Sql server 2005里面也提供了类似的函数。
              string format = "SELECT {0} FROM (SELECT RowNum AS RowIndex, {0} FROM ("

                           + "SELECT {0} FROM {1}{2}{3}) WHERE RowNum <= {4}) WHERE RowIndex > {5}";

     其他的, 比方说

    mysql:"SELECT * LIMIT {0} OFFSET {1}"

     PostgreSql: "SELECT * LIMIT {0} OFFSET {1}"

           Sqlite: "SELECT * LIMIT {0} OFFSET {1}"

           Firebird: "SELECT FIRST {0} SKIP {1} *"

           DB2: null -- Not Supported

           VistaDB: "SELECT TOP {2}, {0} *"

      我现在用的是ORM工具,他支持对常见的各种数据库分页操作。也支持自己写分页扩展。

     

    关于分页的方案

    1:UI分页,数据库取出所有数据

       这样做的缺点显而易见,不论界面上显示多少,你都是把所有数据都去出来的,至少在内存里面。这个效率的损失就相当严重。

       最经典的DataGrid(.net1.1)的用法就是这样:设置可以分页的属性,取出数据,然后绑定到控件。这样做,其实就是一种全部依赖UI分页的做法

       当然,在DataGrid里面还支持另外一种实现,就是使用虚拟的分页,VirtualPageNumber。自己取出数据有多少页,然后取出其中一页数具进行绑定。这样做就避免了这个缺陷。

       遗憾的是在.net2.o里面,GridView反而没有了这个实现(稍后再说这个问题)

    2:UI只显示其中一页,数据库实现分页

       这个就是刚才上边说的DataGrid实现分页的第二种方法。优点是,效率大有提高,特别是数据量比较大的时候。

    数据分页的简单实现

    有了上边的准备,我们来说一下如何实现分页。

    1:UI控件的选择

       由于Repeater和DataList本身不支持分页,所以我们如果选择他的话,注定了要自己实现分页了。

    我们选择方案当然是第二种分页:数据库分页和界面分页结合的方式。

    首先,我们要做的就是为提供Pager. 最简单的,放置几个LinkButtom(<<,<,xx of xxx,>,>>)。这些用来触发命令

                      <asp:LinkButton ID="lb_first" runat="server" OnClick="lb_first_Click"><<</asp:LinkButton>

                      <asp:LinkButton ID="lb_prv" runat="server" OnClick="lb_prv_Click"><</asp:LinkButton>

                      <asp:Label ID="lbl_pager" runat="server" Text="0 of 0"></asp:Label>

                      <asp:LinkButton ID="lb_next" runat="server" OnClick="lb_next_Click">></asp:LinkButton>

                  <asp:LinkButton ID="lb_last" runat="server" OnClick="lb_last_Click">>></asp:LinkButton>

    然后让你的控件可以识别这些属性:TotalPageCount;CurrentPageIndex,PageSize

    剩下的就是写程序每次绑定一下数据了。

       

     1 protected void lb_first_Click(object sender, EventArgs e)
     2    {
     3        this.CurrentPageIndex = 1;
     4        this.BindInspection();
     5    }
     6    protected void lb_prv_Click(object sender, EventArgs e)
     7    {
     8        this.CurrentPageIndex--;
     9        this.BindInspection();
    10    }
    11    protected void lb_next_Click(object sender, EventArgs e)
    12    {
    13        this.CurrentPageIndex++;
    14        this.BindInspection();
    15    }
    16    protected void lb_last_Click(object sender, EventArgs e)
    17    {
    18        this.CurrentPageIndex = this.TotalPageCount;
    19        this.BindInspection();
    20    }
    21   //property
    22   private int CurrentPageIndex
    23    {
    24        get
    25        {
    26            if (Session["CurrentPageIndex"] == null)
    27                Session["CurrentPageIndex"] = 1;
    28            return Convert.ToInt32(Session["CurrentPageIndex"]);
    29        }
    30        set { Session["CurrentPageIndex"] = value; }
    31    }
    32    private int TotalPageCount
    33    {
    34        get
    35        {
    36            if (Session["TotalPageCount"] == null)
    37                Session["TotalPageCount"] = 1;
    38            return Convert.ToInt32(Session["TotalPageCount"]);
    39        }
    40        set { Session["TotalPageCount"] = value; }
    41    }
    42



        简单的绑定代码:

        

     1          //bind it here
     2
     3          //set property
     4           this.TotalPageCount = ps.PageCount;
     5 
     6
     7           if (this.CurrentPageIndex >= this.TotalPageCount)
     8                this.lb_next.Enabled = false;
     9            else
    10                this.lb_next.Enabled = true;
    11            if (this.CurrentPageIndex <= 1)
    12                this.lb_prv.Enabled = false;
    13            else
    14                this.lb_prv.Enabled = true;
    15            this.lbl_pager.Text = String.Format("{0} of {1}", this.CurrentPageIndex.ToString(), this.TotalPageCount.ToString());
    16
    17

    如果你选择了GridView.没有关系,依然可以使用这种方案。

    但是,也有其他选择,那就是使用DataSource控件。我不喜欢用SqlDataSource(觉得把逻辑层高的不清不楚),我一般使用ObjectDataSource.

    这里有详细的使用方法:Asp.net2.0:如何使用ObjectDataSource(配合ORM),http://www.cnblogs.com/dlwang2002/archive/2006/06/11/422991.

    2:选择适当的数据操作层,用好数据库分页

      刚才提到了,我用的是一个ORM,它提供了这些实现,非常好用。

    当然,终极解决方法是:做好你的逻辑,不要让每次取出的数据量过大。

  • 相关阅读:
    前端之HTML
    面向对象编程思想
    【统计】Causal Inference
    Python 最常见的 170 道面试题全解析:2019 版
    面试mysql表设计要注意啥
    数据分析资料汇总
    【crunch bang】论坛tint2配置讨论贴
    【crunch bang】增加壁纸图片文件
    【linux】xx is not in the sudoers file 解决办法
    【crunch bang】安装firefox,删除iceweasel
  • 原文地址:https://www.cnblogs.com/cugwx/p/3616577.html
Copyright © 2020-2023  润新知