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






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

背景
为了实现解决方案,逻辑非常简单。通常,我们使用数据表或数据集来绑定到 gridview 或任何数据绑定控件。数据表的问题在于它会加载所有记录,然后绑定到 Grid View 上的特定页面。假设您有 100 万条记录,那么它将花费 x 秒来填充这 100 万条记录并绑定到 Grid,而 Grid 只会显示一个包含 10 条记录的页面。现在,如果我们以某种方式让数据表只填充我们想要显示的那些记录,它将减少填充的时间。为了简化,我们告诉数据表从记录 2000 - 2010 或从 20,000 到 20,010 开始填充 10 条记录。这样,我们可以节省大量时间。
为了实现上述目标,我们将使用以下逻辑
- 使用查询执行数据读取器。
- 循环数据读取器到我们想要开始获取记录的位置。
- 获取所需的记录。
- 将此数据转换为数据表。
- 中断并退出循环。
- 返回数据表。
您可能会争辩说,像这样循环遍历完整记录与填充数据表是一样的。但是通过附加的示例,我已经在我的计算机上测试过(双核 1.2 Ghz,2 GB RAM),获取 250 万条记录需要 39 秒,而使用此数据读取器需要 2.27 秒。所以现在让我们快速进入代码,看看事情是如何运作的。
Using the Code
逻辑的主要核心是在Common.cs中找到的函数“DataReaderToDataTable
”。它有一个参数作为 sQuery
、iStart
、iEndRow
。
- 此函数执行查询并根据
StartRow
、EndRow
返回带有记录的DataTable
- 它首先通过 SQL 查询执行
DataReader
。 - 执行查询会非常快,因为到目前为止还没有完成任何数据处理。
- 此后,它会将
TableSchema
作为行加载到schematable(DataTable)
中。 - 它将创建一个新的数据表,并通过循环
schematable
来加载其具有正确数据类型的列。 - 此后,
while
循环将开始循环,直到它到达istart
变量,从那里开始获取数据。 - 它将获取数据直到收到
iEnd
变量,之后它将中断循环。 - 数据表将被返回到调用函数。
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 日:首次发布