概述
分頁就是把數據分成一頁一頁的,然後再顯示出來,從這句話的理解中我們可以有多種方案:一次從數據庫中只取出當前頁面的數據,如需顯示下一頁數據,再從數據庫中取出本次頁面的數據;一次從數據庫中取出所有的數據,然後,顯示顯示當前頁面的數據,如需顯示下一頁數據,再一次從數據庫中取出所有數據,顯示下一頁數據,一次類推;一次從數據庫中取出所有的數據,然後,顯示本次頁面數據,如需顯示下一頁的數據,不需要再一次從數據庫取出數據,根據之前的數據,顯示下一頁面的數據。具體每種方案的優缺點、適用於哪種情況,在這裡就不說了,合理使用這幾種方案,可以使我們的系統更加的完美。
下面是一些關於這幾種方案在實現過程中需要掌握的一些知識。
GridView控件
使用GridView控件實現數據分頁的功能,核心代碼如下:
[csharp] view plaincopyprint?
//打開分頁功能
GridView1.AllowPaging = true;
//確定每頁最大記錄數
GridView1.PageSize = 2;
//綁定數據源
GridView1.DataSource = dt;
GridView1.DataBind();
//GridView控件的PageIndexChanging事件裡代碼的功能:實現點擊某頁就轉化到某頁數據
//把要轉化到的頁數賦值給控件的PageIndex屬性
GridView1.PageIndex = e.NewPageIndex;
//從新綁定數據
……
//打開分頁功能
GridView1.AllowPaging = true;
//確定每頁最大記錄數
GridView1.PageSize = 2;
//綁定數據源
GridView1.DataSource = dt;
GridView1.DataBind();
//GridView控件的PageIndexChanging事件裡代碼的功能:實現點擊某頁就轉化到某頁數據
//把要轉化到的頁數賦值給控件的PageIndex屬性
GridView1.PageIndex = e.NewPageIndex;
//從新綁定數據
……
AspNetPager分頁控件
我們可以把分頁這個整體分為為兩個過程:分頁邏輯運算和頁面顯示。GridView控件具有整個分頁的功能,但是其分頁邏輯運算不怎麼好,所以,有了AspNetPager控件(沒有顯示頁面數據的功能),對於AspNetPager控件,其在分頁過程中用到的代碼如下:
[csharp] view plaincopyprint?
//設置總記錄數的大小
AspNetPager.RecordCount = 10;
//設置每頁記錄數的大小
AspNetPager.PageSize = 2;
//AspNetPager控件的PageChanging事件裡的代碼如下
AspNetPager.CurrentPageIndex = e.NewPageIndex;
//重新綁定數據
……
//設置總記錄數的大小
AspNetPager.RecordCount = 10;
//設置每頁記錄數的大小
AspNetPager.PageSize = 2;
//AspNetPager控件的PageChanging事件裡的代碼如下
AspNetPager.CurrentPageIndex = e.NewPageIndex;
//重新綁定數據
……
數據庫
對於一次些取完所有數據的SQL代碼在這裡就不說了,需要說一下的是另一種情況:一次取記錄中一部分記錄的情況。根據要求,我們可以得出SQL語句中應該包含每一頁的記錄數和頁面示數,並且,我們還有保證他的正確性。具體代碼如下:
[sql
--通用的SQL代碼
select top 每頁顯示的記錄數 * from A
where id not in
(select top (當前的頁數-1) * 每頁顯示的記錄數 id from A order by id desc)
order by id desc
解釋:這個是比較通用的方法,主要意思是:總數為100人,按照順序排好,A選前20個人,B選前10個人,從A從取出10個跟B中人不同的人。
-- 另一種SQL語句如下:
with tempTB as (
SELECT ROW_NUMBER() OVER (ORDER BY id desc)AS Row,
...
)
SELECT * FROM tempTB where Row between @startIndex and @endIndex
--通用的SQL代碼
select top 每頁顯示的記錄數 * from A
where id not in
(select top (當前的頁數-1) * 每頁顯示的記錄數 id from A order by id desc)
order by id desc
解釋:這個是比較通用的方法,主要意思是:總數為100人,按照順序排好,A選前20個人,B選前10個人,從A從取出10個跟B中人不同的人。
-- 另一種SQL語句如下:
with tempTB as (
SELECT ROW_NUMBER() OVER (ORDER BY id desc)AS Row,
...
)
SELECT * FROM tempTB where Row between @startIndex and @endIndex
解釋:這個SQL代碼我們需要知道兩個點:CTE和row_number() over (partition by column order by column)。
CTE
CTE是公共表表達式,其產生的最大好處就是提升了SQL代碼的可讀性,當然,一定程度上也是提高了系統的性能,它是一個存儲結果集的內存表(數據太多的話也會用到虛擬內存),且結果集只對其後一句SQL語句有效,並且,這個後一句SQL語句可以多次出現該結果集,CTE主要是遞歸的運用,下面是關於CTE的一些代碼:
[sql]
--創建
with CTE_Test1
as
(
select id,title,content from news
), --引用多個不同的結果集的CET,可以同時創建多個
CTE_Test2
as
(
select id,categoryId from news
)
--使用;CTE_Test只能被緊跟其後一條SQL語句一次或多次訪問
select * from CTE_Test1 as a
inner join CTE_Test2 as b
on a.id = b.id
order by a.id desc
--創建(遞歸)
with CTE_Test(id,categoryId,title)
as
(
--基本語句
select id,categoryId,title from news
union all
--遞歸語句
select news.id,news.categoryId,news.title from news inner join CTE_Test on news.id = CTE_Test.id
)
--使用
select * from CTE_Test
option(maxrecursion 2) --指定最大遞歸次數為2
--創建
with CTE_Test1
as
(
select id,title,content from news
), --引用多個不同的結果集的CET,可以同時創建多個
CTE_Test2
as
(
select id,categoryId from news
)
--使用;CTE_Test只能被緊跟其後一條SQL語句一次或多次訪問
select * from CTE_Test1 as a
inner join CTE_Test2 as b
on a.id = b.id
order by a.id desc
--創建(遞歸)
with CTE_Test(id,categoryId,title)
as
(
--基本語句
select id,categoryId,title from news
union all
--遞歸語句
select news.id,news.categoryId,news.title from news inner join CTE_Test on news.id = CTE_Test.id
)
--使用
select * from CTE_Test
option(maxrecursion 2) --指定最大遞歸次數為2
臨時表是為了記錄大量的中間集;視圖是為了簡化復雜的聯表查詢;表變量是為了快速記錄少量的中間集;CET是為了SQL代碼的可讀性。以上是筆者認為它們的主要作用,具體就不解釋了。
row_number() over (partition by column order by column)
這個是一個函數,具體的作用就是在查詢的結果集中添加一個字段,並且順序的寫出序號;partition by column的作用是是該函數分塊進行書寫相應的序號,例:A塊和B塊的序號的書寫都是從1開始的。
DataTable向DataTalbe之間數據傳遞
當采用一次訪問數據,數次使用數據的方案時,我們的基本操作就是,把總數據放到一個DataTable中,每一頁的數據放到另一個DataTable中,我們綁定的時候,綁定每一頁的數據,下面是DataTable和DataTable之間數據的傳遞代碼:
[csharp]
//傳遞表頭信息
//方法一
for (int i = 0; i < dt1.Columns.Count; i++)
{
dt2.Columns.Add(dt1.Columns[i].ColumnName);
}
//方法二
//復制一個相同的對象
dt2 = dt1.Copy();
//清空裡面的數據
dt2.Rows.Clear();
//方法三
//復制一個對象,但該對象裡沒有相應的數據
dt2 = dt1.Clone();
//傳遞具體數據信息
for (int i = 0; i < dt1.Rows.Count; i++)
{
//方法一:添加一行數據
DataRow drq = dt2.NewRow();
drq.ItemArray = dt1.Rows[i].ItemArray;
dt2.Rows.Add(drq);
//方法二:添加一行數據
//dt2.ImportRow(dt.Rows[0]);
}
//傳遞表頭信息
//方法一
for (int i = 0; i < dt1.Columns.Count; i++)
{
dt2.Columns.Add(dt1.Columns[i].ColumnName);
}
//方法二
//復制一個相同的對象
dt2 = dt1.Copy();
//清空裡面的數據
dt2.Rows.Clear();
//方法三
//復制一個對象,但該對象裡沒有相應的數據
dt2 = dt1.Clone();
//傳遞具體數據信息
for (int i = 0; i < dt1.Rows.Count; i++)
{
//方法一:添加一行數據
DataRow drq = dt2.NewRow();
drq.ItemArray = dt1.Rows[i].ItemArray;
dt2.Rows.Add(drq);
//方法二:添加一行數據
//dt2.ImportRow(dt.Rows[0]);
} 通過邏輯運算,找到從哪一行開始賦值。
實例1
下面是采用每次從數據庫取出一頁數據的方案的實例,采用GridView和AspNetPager結合,具體代碼如下
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//總的記錄數是多少
anp.RecordCount = 4;
//每頁顯示的記錄數
anp.PageSize = 2;
//獲得數據
GetSource();
//綁定數據
BandSource();
}
}
//獲得源數據
private void GetSource()
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "Data Source=ip地址;Initial Catalog=數據庫;User ID=登陸名;Pwd=密碼";
cn.Open();
string strSql = "select top (@每頁記錄數) * from news where id not in (select top (@當前頁減一的記錄和) id from news order
by id desc) order by id desc";
SqlCommand cmd = new SqlCommand(strSql,cn);
SqlParameter[] sqlParams = new SqlParameter[] { new SqlParameter("@每頁記錄數", anp.PageSize), new SqlParameter("@當前頁減
一的記錄和", (anp.CurrentPageIndex - 1) * anp.PageSize) };
cmd.Parameters.AddRange(sqlParams);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
//綁定源數據
private void BandSource()
{
//綁定數據
GridView1.DataSource = dt; //設定數據源
GridView1.DataBind(); //綁定數據源
}
//索引頁發生改變
protected void AspNetPager1_PageChanging(object src, Wuqi.Webdiyer.PageChangingEventArgs e)
{
//獲得當前索引頁示數
anp.CurrentPageIndex = e.NewPageIndex;
//重新獲得數據,綁定數據
GetSource();
BandSource();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//總的記錄數是多少
anp.RecordCount = 4;
//每頁顯示的記錄數
anp.PageSize = 2;
//獲得數據
GetSource();
//綁定數據
BandSource();
}
}
//獲得源數據
private void GetSource()
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "Data Source=ip地址;Initial Catalog=數據庫;User ID=登陸名;Pwd=密碼";
cn.Open();
string strSql = "select top (@每頁記錄數) * from news where id not in (select top (@當前頁減一的記錄和) id from news order
by id desc) order by id desc";
SqlCommand cmd = new SqlCommand(strSql,cn);
SqlParameter[] sqlParams = new SqlParameter[] { new SqlParameter("@每頁記錄數", anp.PageSize), new SqlParameter("@當前頁減
一的記錄和", (anp.CurrentPageIndex - 1) * anp.PageSize) };
cmd.Parameters.AddRange(sqlParams);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
//綁定源數據
private void BandSource()
{
//綁定數據
GridView1.DataSource = dt; //設定數據源
GridView1.DataBind(); //綁定數據源
}
//索引頁發生改變
protected void AspNetPager1_PageChanging(object src, Wuqi.Webdiyer.PageChangingEventArgs e)
{
//獲得當前索引頁示數
anp.CurrentPageIndex = e.NewPageIndex;
//重新獲得數據,綁定數據
GetSource();
BandSource();
}
}
}
實例2
該實例是多次訪問數據庫,每一次返回所有數據的那個方案,采用GridView控件,具體代碼如下:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BLL;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//開啟分頁的功能
GridView2.AllowPaging = true;
//每頁的大小為1
GridView2.PageSize = 1;
//綁定數據,並顯示第一頁
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
//索引頁發生改變
protected void GridView2_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
//設置顯示的頁碼
GridView1.PageIndex = e.NewPageIndex;
//從新綁定數據
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BLL;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//開啟分頁的功能
GridView2.AllowPaging = true;
//每頁的大小為1
GridView2.PageSize = 1;
//綁定數據,並顯示第一頁
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
//索引頁發生改變
protected void GridView2_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
//設置顯示的頁碼
GridView1.PageIndex = e.NewPageIndex;
//從新綁定數據
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
}
實例1和2的前台界面設計沒有貼出相應的代碼,還有,實例2運用的是經典3層架構,BLL層的代碼也沒有貼出來,所以,如果要是用上述代碼的話,還是要多多注意點。