zoukankan      html  css  js  c++  java
  • 浅谈分页技术

    这几天看到几篇关于分页的文章,觉得有些东西可以分享一下。这里提供一些关于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工具,他支持对常见的各种数据库分页操作。也支持自己写分页扩展。

     

    关于分页的方案

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

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

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

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

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

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

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

    数据分页的简单实现

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

    1UI控件的选择

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

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

    首先,我们要做的就是为提供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

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

          protected void lb_first_Click(object sender, EventArgs e)
        {
            this.CurrentPageIndex = 1;
            this.BindInspection();
        }
        protected void lb_prv_Click(object sender, EventArgs e)
        {
            this.CurrentPageIndex--;
            this.BindInspection();
        }
        protected void lb_next_Click(object sender, EventArgs e)
        {
            this.CurrentPageIndex++;
            this.BindInspection();
        }
        protected void lb_last_Click(object sender, EventArgs e)
        {
            this.CurrentPageIndex = this.TotalPageCount;
            this.BindInspection();
        }
        //property
        private int CurrentPageIndex
        {
            get
            {
                if (Session["CurrentPageIndex"] == null)
                    Session["CurrentPageIndex"] = 1;
                return Convert.ToInt32(Session["CurrentPageIndex"]);
            }
            set { Session["CurrentPageIndex"] = value; }
        }
        private int TotalPageCount
        {
            get
            {
                if (Session["TotalPageCount"] == null)
                    Session["TotalPageCount"] = 1;
                return Convert.ToInt32(Session["TotalPageCount"]);
            }
            set { Session["TotalPageCount"] = value; }
        }

    简单的绑定代码:

    //bind it here

            //set property
            this.TotalPageCount = ps.PageCount;


            if (this.CurrentPageIndex >= this.TotalPageCount)
                this.lb_next.Enabled = false;
            else
                this.lb_next.Enabled = true;
            if (this.CurrentPageIndex <= 1)
                this.lb_prv.Enabled = false;
            else
                this.lb_prv.Enabled = true;
            this.lbl_pager.Text = String.Format("{0} of {1}", this.CurrentPageIndex.ToString(), this.TotalPageCount.ToString());


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

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

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

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

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

     

    当然,终极解决方法是:做好你的逻辑,不要让每次取出的数据量过大。
    作者:Frederick Yang
    出处:http://www.cnblogs.com/yangtongnet/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    MVP模式与MVVM模式
    webpack的配置处理
    leetcode 287 Find the Duplicate Number
    leetcode 152 Maximum Product Subarray
    leetcode 76 Minimum Window Substring
    感知器算法初探
    leetcode 179 Largest Number
    leetcode 33 Search in Rotated Sorted Array
    leetcode 334 Increasing Triplet Subsequence
    朴素贝叶斯分类器初探
  • 原文地址:https://www.cnblogs.com/yangtongnet/p/1444739.html
Copyright © 2011-2022 走看看