這裡要說的不僅僅是一個分頁控件,而是一套解決方案,包括如何顯示資料、顯示分頁導航,如何得到分頁用的sql語句(等效于存儲過程),如何提取資料,如何綁定控件,如何響應事件,添加、修改、删除資料後如何更新,如何查詢資料等等。一整套完整的解決方案。
這個方案要有幾個特點:
1、支援多種資料庫,可以提供多個分頁算法以便于支援多種資料庫。
2、可以在不同的要求下選用最優的分頁算法。比如如果隻需要按照主鍵排序,那麼選擇Max分頁算法無疑是最快的一種分頁算法。
3、按需所取。不管是哪一種分頁算法,都要達到按需所取。假設一頁顯示20條記錄,那麼從資料庫裡面最多隻提取20條記錄,不可以多取一條。
4、使用簡單。無論是更換分頁算法,更換資料庫,還是處理分頁的事件,都是很簡單的幾行代碼即可搞定。
5、很友善的實作資料查詢的功能。查詢後顯示資料,查詢後修改、删除資料,修改、删除後重新顯示資料等。
6、每一個部分都可以替換。
7、支援海量資料。無論資料多還是少,都要适合,而且要盡量快。
分頁解決方案的組成部分
顯示資料的控件、分頁控件、分頁算法、資料通路函數庫、資料庫
如:GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + SQL Server2000
1、顯示資料的控件可以是GridView、DetailsView、FormView、Repeater、DataGrid、DataList、CheckBoxList、RadioButtonList等。(控件的繼承關系可以看這裡http://www.cnblogs.com/jyk/archive/2009/04/29/1446033.html 這是.net 裡面帶的幾個常用控件的繼承樹)。也可以支援直接傳回DataTable等記錄集。
2、分頁控件,可以是QuickPager也可以是吳旗娃的分頁控件,也可以是EasyTools等其他的分頁控件。
3、分頁算法目前還沒有發現同類的,硬要算的話,儲存過程有一點點類似。
QuickPager_SQL 原來是QuickPager裡面的一部分,現在獨立出來,可以單獨使用了。
4、資料通路函數庫可以換成SQLHelp、微軟的企業庫等,當然需要其他的實作一個接口(IDALforPager)。
5、資料庫可以是Access、Excel、SQL Server,理論上也支援Orcale、MySQL等,隻是沒有安裝這些資料庫,是以還沒有具體實作。
(至于ORM嘛,不是太了解,不知道能不能和哪個部分替換。)
各個部分之間的關系
1、QuickPager與QuickPager_SQL
這個就像SqlCommand和SqlConnection的關系一樣。
SqlConnection cn = new SqlConnection();
SqlCommand cm = new SqlCommand();
cm.Connection = cn;
cm.Connection.Open();
同樣,QuickPager 裡面一個一個成員的類型就是PagerSQL(也就是QuickPager_SQL)。
2、QuickPager與DataAccessLibrary
他們是通過一個接口(IDALforPager)聯系在一起的,
Code
public interface IDALforPager
{
/// <summary>
/// 傳入SQL語句,傳回DataTable的接口
/// </summary>
/// <param name="sql">SQL語句</param>
/// <returns></returns>
DataTable ExecuteFillDataTable(string sql);
/// 傳入SQL語句,傳回第一條記錄,第一個字段的值的接口
/// <param name="sql"></param>
string ExecuteString(string sql);
/// 記錄出錯的描述資訊
string ErrorMessage { get; }
}
3、QuickPager與顯示資料的控件
為了便于使用,就是說想在使用的時候盡量的少寫代碼,是以我是把顯示資料的控件傳遞到了分頁控件裡面,然後在需要綁定控件的時候,采用as的方式來判斷是哪種控件,然後在強制轉換,最後實作綁定控件的目的。研究了一下.net裡的一些控件的繼承關系,發現雖然控件很多,但是我隻需要做三次判斷就可以了,這就是基類的好處吧。
private void DataBind(System.Web.UI.Control control, MarshalByValueComponent dt)
{
if (control == null)
return;
//為什麼沒有一個統一的DataSource呢?
BaseDataBoundControl tmpBaseDataBoundControl = control as BaseDataBoundControl;
if (tmpBaseDataBoundControl != null)
{
tmpBaseDataBoundControl.DataSource = dt;
tmpBaseDataBoundControl.DataBind();
}
else
Repeater tmpRepeater = control as Repeater;
if (tmpRepeater != null)
{
tmpRepeater.DataSource = dt;
tmpRepeater.DataBind();
}
else
BaseDataList tmpBaseDataList = control as BaseDataList;
if (tmpBaseDataList != null)
{
tmpBaseDataList.DataSource = dt;
tmpBaseDataList.DataBind();
}
else
//不在判斷範圍内,退出
return;
}
4、QuickPager_SQL與DataAccessLibrary、顯示資料的控件沒有任何關系。
5、QuickPager與QuickPager_UI
QuickPager_UI 也是分頁控件的一個成員,因為至少有三種分頁方式(PostBack、URL、XMLHttp),是以呢我采用了基類和子類的方式來實作這種需求,以達到可以随時擴充的需求。
分頁解決方案從使用方法的角度來說,有兩種方式。
第一種就是“自動運作”,設定屬性,其他的就不用管了(僅限于QuickPager,其他的分頁控件可能不支援);
另一種是“手動運作”,手動運作就要多做一些事情了(其他分頁控件的情況)。
分頁解決方案從送出資料的角度,有三種方式。
PostBack、URL、XMLHttp。當然這三種也是針對于QuickPager來說的,其他的分頁控件是否支援,就看作者的了。
使用方法:
時間比較緊,是以這裡先說一下使用方法是自動運作、PostBack的情況。
1、一般顯示資料
protected override void OnInit(EventArgs e)
{
base.OnInitComplete(e);
//資料通路函數庫
DataAccessLibrary dal = DALFactory.CreateDAL();
Pager1.DAL = dal;
//定義QuickPager_SQL
PagerSQL pagerSQL = PagerSQL.Create(PagerSQLKind.MaxMin);
pagerSQL.Page = this;
Pager1.ManagerPageSQL = pagerSQL;
Pager1.ShowDataControl = this.GV; //設定顯示資料的控件
protected void Page_Load(object sender, EventArgs e)
if (!Page.IsPostBack)
SetPagerInfo(); //設定表名、字段名等
給QuickPager_SQL 設定屬性,以便拼接SQL#region 給QuickPager_SQL 設定屬性,以便拼接SQL
private void SetPagerInfo()
Pager1.ManagerPageSQL.TableName = "News_NewsInfo"; //表名或者視圖名稱
Pager1.ManagerPageSQL.TableShowColumns = "*"; //需要顯示的字段
Pager1.ManagerPageSQL.TableIDColumn = "NewsID"; //主鍵名稱,不支援複合主鍵
Pager1.ManagerPageSQL.TableOrderByColumns = "NewsID"; //排序字段,根據分頁算法而定,可以支援多個排序字段
Pager1.ManagerPageSQL.TableQuery = ""; //查詢條件
Pager1.PageSize = 4; //一頁顯示的記錄數
#endregion
2、查詢資料
處理查詢資料的情況#region 處理查詢資料的情況
protected void Btn_Search_Click(object sender, EventArgs e)
//擷取查詢條件
string query = "";
string tmp = "";
tmp = this.Txt_Title.TextTrimNone;
if (tmp.Length > 0)
if (query.Length == 0)
query = " title like '%" + tmp + "%'";
else
query += " and title like '%" + tmp + "%'";
//還可以添加其他的查詢條件,這裡省略
//給QuickPager_SQL 設定查詢條件
this.Pager1.ManagerPageSQL.TableQuery = query; //設定查詢條件
this.Pager1.BindFirstPage(); //重新綁定控件,顯示第一頁的資料
3、添加、修改、删除後重新顯示資料
添加後重新顯示資料#region 添加後重新顯示資料
protected void Btn_Add_Click(object sender, EventArgs e)
//添加新的資料後,顯示第一頁的資料
this.Pager1.BindFirstPage();
修改資料後重新顯示目前頁的資料#region 修改資料後重新顯示目前頁的資料
protected void Btn_Mod_Click(object sender, EventArgs e)
//比如在第三頁修改了一條資料,修改完畢後,重新顯示第三頁的資料。
this.Pager1.BindThisPage();
添加後重新顯示資料#region 添加後重新顯示資料
protected void Btn_Del_Click(object sender, EventArgs e)
//比如在第三頁删除了一條資料後,重新顯示第三頁的資料。
//和修改資料後重新顯示的差別在于,删除資料後需要重新統計總記錄數,和總頁數
this.Pager1.BindThisPageForDelete();
關于三層
現在三層還是很流行的,那麼我的這個算不算是三層呢?其實算不算對于我來說是無所謂的事情,又沒有誰規定,現在寫項目必須三層(或者MVC),否則就是不合格産品。既然沒有這個規定,那麼我又為何要在乎是否可以靠到三層結構上呢?
另外呀,我覺得這麼寫代碼挺簡單的,要說簡化,還确實是有簡化的空間,但是說要往三層結構上面靠攏,我還确實不知道應該怎麼做。
就像http://www.cnblogs.com/wisdomqq/archive/2009/04/29/1446579.html 裡說的,“經常看到有的朋友使用三層結構或者MVC模式,比較生硬,強行進行拆分代碼,使得業務代碼分散在各個角落,反而更難閱讀和維護了。”
我覺得這麼寫,對于簡單的應用是沒有什麼問題的,當然了複雜的情況是有其他的方法來解決的。
代碼下載下傳:
<a href="http://www.cnblogs.com/jyk/archive/2008/07/29/1255891.html">http://www.cnblogs.com/jyk/archive/2008/07/29/1255891.html</a>
ps:今天先寫這麼多,以後再詳細說明。