65.9K
CodeProject 正在变化。 阅读更多。
Home

GridView 中不更改/破坏 SQL 查询的自定义分页

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.40/5 (4投票s)

2010年11月30日

CPOL

3分钟阅读

viewsIcon

25003

downloadIcon

425

任何数据库上的自定义分页

引言

自定义分页的思路并不新鲜,已经存在很长时间了。我看到的大多数程序都是通过存储过程或查询来实现自定义分页,这当然是最好的方法,但是如果您已经构建了一个项目,并且不想更改存储过程或查询,因为这会带来其他错误并需要大量测试,该怎么办?或者,如果您使用的是 SQL Server 2000,它不支持 Row_Number() 函数,因此您必须采用很长的方式进行自定义分页,该怎么办?

Paging.jpg

背景

为了实现解决方案,逻辑非常简单。通常,我们使用数据表或数据集来绑定到 gridview 或任何数据绑定控件。数据表的问题在于它会加载所有记录,然后绑定到 Grid View 上的特定页面。假设您有 100 万条记录,那么它将花费 x 秒来填充这 100 万条记录并绑定到 Grid,而 Grid 只会显示一个包含 10 条记录的页面。现在,如果我们以某种方式让数据表只填充我们想要显示的那些记录,它将减少填充的时间。为了简化,我们告诉数据表从记录 2000 - 2010 或从 20,000 到 20,010 开始填充 10 条记录。这样,我们可以节省大量时间。

为了实现上述目标,我们将使用以下逻辑

  1. 使用查询执行数据读取器。
  2. 循环数据读取器到我们想要开始获取记录的位置。
  3. 获取所需的记录。
  4. 将此数据转换为数据表。
  5. 中断并退出循环。
  6. 返回数据表。

您可能会争辩说,像这样循环遍历完整记录与填充数据表是一样的。但是通过附加的示例,我已经在我的计算机上测试过(双核 1.2 Ghz,2 GB RAM),获取 250 万条记录需要 39 秒,而使用此数据读取器需要 2.27 秒。所以现在让我们快速进入代码,看看事情是如何运作的。

Using the Code

逻辑的主要核心是在Common.cs中找到的函数“DataReaderToDataTable”。它有一个参数作为 sQueryiStartiEndRow

  1. 此函数执行查询并根据StartRowEndRow返回带有记录的DataTable
  2. 它首先通过 SQL 查询执行 DataReader
  3. 执行查询会非常快,因为到目前为止还没有完成任何数据处理。
  4. 此后,它会将 TableSchema 作为行加载到 schematable(DataTable) 中。
  5. 它将创建一个新的数据表,并通过循环 schematable 来加载其具有正确数据类型的列。
  6. 此后,while 循环将开始循环,直到它到达 istart 变量,从那里开始获取数据。
  7. 它将获取数据直到收到 iEnd 变量,之后它将中断循环。
  8. 数据表将被返回到调用函数。
internal static DataTable DataReaderToDataTable(string sQuery, int iStart, int iEnd)
{
            DataTable schematable = null;
            DataTable dt = null;
            SqlCommand cmdsql;
            SqlDataReader dr = null;
            SqlConnection conn = null;
            long icount = 0;
            try
            {
                //Open the connection and execute the Data Reader          
                conn = new SqlConnection(ConnString);
                conn.Open();
                cmdsql = new SqlCommand(sQuery, conn);
                dr = cmdsql.ExecuteReader(CommandBehavior.CloseConnection);
                schematable = dr.GetSchemaTable();
                dt = new DataTable();

                //Get the Schema of Tables Columns and its types, 
                //and load the same into DataTable.
                for (int i = 0; i <= schematable.Rows.Count - 1; i++)
                {
                    DataRow dRow = schematable.Rows[i];
                    DataColumn column = new DataColumn();
                    column.DataType = System.Type.GetType(dRow["DataType"].ToString());
                    column.AllowDBNull = 
			(dRow["AllowDBNull"].ToString() == "True" ? true : false);
                    column.ColumnName = dRow["ColumnName"].ToString();
                    column.Caption = dRow["ColumnName"].ToString();
                    
                    dt.Columns.Add(column);
                    //More DataTable property can be added as required.
                }
                if (iStart == 0) iStart = 1;
                if (iEnd == 0) iEnd = 1;
                icount = 1;

                //Loop the Reader which is executed till the Start and Variable, 
                //Fetch and add the rows one by one to Data Table 
                //Till the End Count is reached.
                // Exit the loop and Return Datable.
                while (dr.Read())
                {
                    if (icount >= iStart && icount <= iEnd)
                    {
                        DataRow dRow = dt.NewRow();
                        for (int i = 0; i <= dr.FieldCount - 1; i++)
                        {
                            dRow[i] = dr.GetValue(i);
                        }
                        dt.Rows.Add(dRow);
                    }
                    else if (icount > iEnd)
                    {
                        break;
                    }
                    icount = icount + 1;
                }
            }
            catch (SystemException ex)
            {
                throw ex;
            }
            finally
            {
                conn.Close();
                conn.Dispose();
                schematable.Dispose();
                dr.Close();
                dr.Dispose();
            }
            return dt;
}

仅使用此函数就足以以另一种方式应用自定义分页。但是,我已经使用 GridView 实现了这一点。

欢迎您提出所有建议以改进此代码。
祝您编码愉快!

历史

  • 2010 年 11 月 30 日:首次发布
© . All rights reserved.