编写自己的高效分页SqlHelper

  这里主要介绍一下使用DataReader读取数据,包括分页读取。DataReader只读向前,DataAdapter的Fill方法是一 次性把查询到的所有数据取出来填充到DataTable或DataSet,下面的方法是使用DataReader只把当前页所需要的数据取出来添加到 DataTable,效率要比使用DataAdapter的Fill方法高得多。

      一、创建一个类库项目,命名为DAO,并创建一个SqlHelper.cs类

using System.Data; using System.Data.SqlClient; namespace DAO { public class SqlHelper { //数据库连接字符串,在实际应用中将其写在配置文件中,不要如此硬编码 private static string ConnString = "server=.;database=test;uid=sa;pwd=123456"; public SqlHelper() { } public static void FillDataTable(string query, DataTable dt) { using (SqlConnection conn = new SqlConnection(ConnString)) { SqlCommand cmd = new SqlCommand(query, conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); int cols = dr.VisibleFieldCount; for (int i = 0; i < cols; i++) { dt.Columns.Add(new DataColumn(dr.GetName(i), dr.GetFieldType(i))); } while (dr.Read()) { DataRow row = dt.NewRow(); for (int i = 0; i < cols; i++) { row[i] = dr[i]; } dt.Rows.Add(row); } dr.Close(); } } ///

/// 分页读取数据 /// /// select查询语句 /// 每页显示数据数 /// 当前页码 /// 存储数据的DataTable实例 public static void FillDataTable(string query,int pageSize,int currentPageIndex, DataTable dt) { //读取数据的开始索引 long startIndex = (currentPageIndex - 1) * pageSize; //读取数据的结束索引 long endIndex = currentPageIndex * pageSize-1; //DataReader读取的当前数据行的索引 long readToIndex = -1; using (SqlConnection conn = new SqlConnection(ConnString)) { SqlCommand cmd = new SqlCommand(query, conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); //数据源中的列数 int cols = dr.VisibleFieldCount; //构造DataTable结构 for (int i = 0; i < cols; i++) { dt.Columns.Add(new DataColumn(dr.GetName(i), dr.GetFieldType(i))); } //读取数据,将数据一行一行添加到DataTable while (dr.Read()) { readToIndex++; //当DataReader指针在开始索引和结束索引闭区间时才读取数据构造DataRow //并添加到DataTable if (readToIndex >= startIndex && readToIndex <= endIndex) { DataRow row = dt.NewRow(); for (int i = 0; i < cols; i++) { row[i] = dr[i]; } dt.Rows.Add(row); } } dr.Close(); } } } }

  二、测试,创建一个网站项目,编译DAO项目,添加对DAO项目的引用

       创建测试表,插入一百万条数据:

declare @num int set @num=1 while(@num<1000001) begin insert BigData values(@num) set @num = @num+1 end

 

      设计如下界面

      编写自己的高效分页SqlHelper_第1张图片

   GridView保持默认设置,不要设置自动分页,下面是5个Button和一个TextBox

  后台代码:

using System; using System.Web.UI.WebControls; using System.Data; using DAO; public partial class _Default : System.Web.UI.Page { DataTable dt = new DataTable(); protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { if (ViewState["CurrentPageIndex"] == null) { ViewState["CurrentPageIndex"] = 1; } BindData(); } } private void BindData() { //SqlHelper.FillDataTableByDataAdapter("select * from BigData", dt); SqlHelper.FillDataTable("select * from BigData", 10, int.Parse(ViewState["CurrentPageIndex"].ToString()), dt); GridView1.DataSource = dt; GridView1.DataBind(); } protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) { DateTime dt1 = DateTime.Now; GridView1.PageIndex = e.NewPageIndex; BindData(); DateTime dt2 = DateTime.Now; TimeSpan ts = dt2 - dt1; Response.Write(ts.Milliseconds.ToString()); } protected void btnFirst_Click(object sender, EventArgs e) { ViewState["CurrentPageIndex"] = 1; BindData(); } protected void btnPrev_Click(object sender, EventArgs e) { ViewState["CurrentPageIndex"] = int.Parse(ViewState["CurrentPageIndex"].ToString()) - 1; BindData(); } protected void btnNext_Click(object sender, EventArgs e) { ViewState["CurrentPageIndex"] = int.Parse(ViewState["CurrentPageIndex"].ToString()) + 1; BindData(); } protected void btnGo_Click(object sender, EventArgs e) { ViewState["CurrentPageIndex"] = txtPage.Text.Trim(); BindData(); } }

  运行后界面:

  编写自己的高效分页SqlHelper_第2张图片

   翻页响应很快,比直接使用DataAdapter的Fill方法填充DataTable,然后使用GridView自动翻页效率高的多。

       数据翻页功能的实现还有其它一些方法,比如TOP、row_number() over (SQL Server 2005/2008)、存储过程等,有兴趣可以测试一下。

        本例提供的方法仅供参考。

你可能感兴趣的:(数据访问)