ASPNet中DataGrid基于Access的快速分頁法_第1頁
ASPNet中DataGrid基于Access的快速分頁法_第2頁
ASPNet中DataGrid基于Access的快速分頁法_第3頁
ASPNet中DataGrid基于Access的快速分頁法_第4頁
ASPNet中DataGrid基于Access的快速分頁法_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、DataGrid基于Access的快速分頁法DataGrid是一個(gè)功能非常強(qiáng)大的ASP.NET Web服務(wù)器端控件,它除了能夠方便地按各種方式格式化顯示表格中的數(shù)據(jù),還可以對表格中的數(shù)據(jù)進(jìn)行動(dòng)態(tài)的排序、編輯和分頁。使Web開發(fā)人員從繁瑣的代碼中解放。實(shí)現(xiàn)DataGrid的分頁功能一直是很多初學(xué)ASP.NET的人感到棘手的問題,特別是自定義分頁功能,實(shí)現(xiàn)方法多種多樣,非常靈活。本文將向大家介紹一種DataGird控件在Access數(shù)據(jù)庫下的快速分頁法,幫助初學(xué)者掌握DataGrid的分頁技術(shù)。目前的分頁方法DataGrid內(nèi)建的分頁方法是使用諸如“ SELECT * FROM 勺SQL語句從數(shù)據(jù)

2、庫表中取出所有的記錄到DataSet中,DataGrid控件綁定到該 DataSet之后,它的自動(dòng)分頁功能會(huì)幫你從該 DataSet中篩選出當(dāng)前分頁的數(shù)據(jù)并顯示出來,其他沒有用的數(shù)據(jù)將被丟 棄。還有一種方法是使用自定義分頁功能,先將DataGrid的AllowCustomPaging屬性設(shè)置為True ,再利用DataAdapter的Fill方法將數(shù)據(jù)的篩選工作提前到填充 DataSet時(shí),而不 是讓DataGrid幫你篩選:該方法首先將來自查詢處的結(jié)果填充到DataSet中,再將不需要顯示的數(shù)據(jù)丟棄。當(dāng)然,自定義分頁功能需要完成的事情還不止這些,本文將在后面詳細(xì)介紹。以上兩種方法的工作原理都

3、是先從數(shù)據(jù)庫中取出所有的記錄,然后篩選出有用的數(shù)據(jù)顯示出來??梢?,兩種方法的效率基本上是一致的,因?yàn)樗鼈冊跀?shù)據(jù)訪問階段并沒有采取有效的措施來減少Access對磁盤的訪問次數(shù)。對于小數(shù)量的記錄,這種開銷可能是比較小的, 如果針對大量數(shù)據(jù)的分頁,開銷將會(huì)非常巨大,從而導(dǎo)致分頁的速度非常的慢。換句話說, 就算每個(gè)DataGrid分頁面要顯示的數(shù)據(jù)只是一個(gè)擁有幾萬條記錄的數(shù)據(jù)庫表的其中10條,每次DataGrid進(jìn)行分頁時(shí)還是要從該表中取出所有的記錄。很多人已經(jīng)意識到了這個(gè)問題, 并提出了解決方法: 用自定義分頁,每次只從數(shù)據(jù)庫中 取出要顯示的數(shù)據(jù)。這樣,我們需要在 SQL語句上下功夫了。由于 Acc

4、ess不支持真正的存 儲過程,在編寫分頁算法上就沒有 SQL Server那么自由了。 SQL Server可以在存儲過程中 利用臨時(shí)表來實(shí)現(xiàn)高效率的分頁算法,受到了廣泛的采用。而對于 Access ,我們必須想辦 法在一條SQL語句內(nèi)實(shí)現(xiàn)最高效的算法。用一條SQL語句取得某段數(shù)據(jù)的方法有好幾種。算法不同,效率也就不同。我經(jīng)過粗略的測試,發(fā)現(xiàn)效率最差的SQL語句執(zhí)行時(shí)耗費(fèi)的時(shí)間大概是效率最高的SQL語句的3倍!而且這個(gè)數(shù)值會(huì)隨著記錄總數(shù)的增加而增加。下面將介紹其中兩條常用的SQL語句。為了方便接下來的討論,我們先約定如下:變量說明變量說明PageSize每貝顯不的記錄總數(shù)MiddleIndex

5、中間蟲的索引PageCount分頁總數(shù)LastIndex最后-頁的索引RecordCount數(shù)據(jù)表的記錄總數(shù)TableName數(shù)據(jù)庫表名稱PageIndex當(dāng)前頁的索引PrimaryKey主鍵字段名稱FirstIndexA頁的索引QueryFields要查詢的字段集變量定義PageCount(int)Math.Ceiling(double)RecordCount / PageSize)FirstIndex0LastIndexPageCount - 1MiddleIndex(int)Math.Ceiling(double)PageCount / 2)- 1先讓我們看看效率最差的SQL語句:SEL

6、ECT TOP PageSize * FROM TableNameWHERE PrimaryKey NOT IN (SELECT TOP PageSize*PageIndex PrimaryKey FROM TableNameORDER BY PrimaryKey ASC)ORDER BY PrimaryKey ASC這條SQL語句慢就慢在 NOTIN這里,主SELECTS句遍歷的每個(gè) PrimaryKey的值都要 跟子SELEC砒句的結(jié)果集中的每一個(gè) PrimaryKey的值進(jìn)行比較,這樣時(shí)間復(fù)雜度非常大。 這里不得不提醒一下大家,平時(shí)編寫SQL語句時(shí)應(yīng)該盡量避免使用NOT IN語句,因?yàn)樗?/p>

7、往往會(huì)增加整個(gè)SQL語句的時(shí)間復(fù)雜度。另一種是使用了兩個(gè) TO刖三個(gè)ORDER BY勺SQL語句,如下所示:SELECT * FROM (SELECT TOP PageSize * FROM (SELECT TOP PageSize*(PageIndex+1) * FROM TableName ORDER BY PrimaryKey ASC)TableA ORDER BY PrimaryKey DESC)TableB ORDER BY PrimaryKey ASC這條SQL語句空間復(fù)雜度比較大。如果要顯示的分頁面剛好是最后一頁,那么它的效率比直接SELEC礎(chǔ)所有的記錄還要低。因此,對于分頁算法

8、,我們還應(yīng)該具體情況具體分析, 不能一概而論。 下面將簡單介紹一下相關(guān)概念, 如果您對主鍵和索引非常熟悉, 可以直接跳 過。有關(guān)主鍵和索引的概念在ACCESS中,一個(gè)表的主鍵(PRIMARY KEY又稱主索引)必然是唯一索引( UNIQUE INDEX),它的值是不會(huì)重復(fù)的。除此之外,索引依據(jù)索引列的值進(jìn)行排序,每個(gè)索引記錄 包含著一個(gè)指向它所引用的數(shù)據(jù)行的指針,這對ORDER BY勺執(zhí)行非常有幫助。我們可以利用主鍵這兩個(gè)特點(diǎn)來實(shí)現(xiàn)對某條記錄的定位,從而快速地取出某個(gè)分頁上要顯示的記錄。舉個(gè)例子,假設(shè)主鍵字段為INTEGER1,在數(shù)據(jù)庫表中,記錄的索引已經(jīng)按主鍵字段的 值升序排好 (默認(rèn)情況下

9、) , 那么主鍵字段值為“11”的記錄的索引,肯定剛好在值為“12”的記錄的索引前面 (假設(shè)數(shù)據(jù)庫表中存在主鍵的值為“12 ”的記錄)。 如果主鍵字段不具備UNIQUE約束,數(shù)據(jù)庫表中將有可能存在兩個(gè)或兩個(gè)以上主鍵字段的值為“11”的記錄,這樣就無法確定這些記錄之間的前后位置了。下面就讓我們看看如何利用主鍵來進(jìn)行數(shù)據(jù)的分段查詢吧??焖俜猪摲ǖ脑砥鋵?shí)該分頁法是從其他方法衍生而來的。 本人對原來的方法認(rèn)真地分析, 發(fā)現(xiàn)通過優(yōu)化和改進(jìn)可以非常有效地提高它的效率。 原算法本身效率很高, 但缺乏對具體問題的具體分析。同一個(gè)分頁算法, 可能在取第一頁的數(shù)據(jù)時(shí)效率非常高, 但是在取最后一頁的數(shù)據(jù)時(shí)可能反而

10、效率更低。經(jīng)過分析,我們可以把分頁算法的效率狀態(tài)分為四種情況:1) PageIndex = FirstIndex2) FirstIndex PageIndex = MiddleIndex3) 3) MiddleIndex PageIndex = LastIndex狀態(tài)( 1 )和(4)分別表示第一頁和最后一頁。它們屬于特殊情況,我們不必對其使用特殊算法,直接用TOP就可以解決了,不然會(huì)把問題復(fù)雜化,反而降低了效率。對于剩下的兩種狀態(tài), 如果分頁總數(shù)為偶數(shù), 我們可以看作是從數(shù)據(jù)庫表中刪掉第一頁和最后一頁的記錄,再把剩下的按前后位置平分為兩部分,即前面的一部分,也就是狀態(tài)(2 ),后面的為另一部

11、分,也就是狀態(tài)(3 );如果分頁總數(shù)為奇數(shù),則屬于中間頁面的記錄歸于前面的部分。這四種狀態(tài)分別對應(yīng)著四組SQL語句,每組SQL語句由升序和降序兩條SQL語句組成。下面是一個(gè)數(shù)據(jù)庫表, 左邊第一列是虛擬的, 不屬于該數(shù)據(jù)庫表結(jié)構(gòu)的一部分, 它表示相應(yīng)記錄所在的分頁索引。該表將用于接下來的SQL語句的舉例中:PageIndexItemIdProductIdPrice00010011$120020011$1310030012$130040012$1120050013$140060013$1230070011$130080012$1540090013$120100013$11由表可得: PageSiz

12、e = 2 , RecordCount = 10 , PageCount = 5升序的SQL語句(1) PageIndex = FirstIndex取第一頁的數(shù)據(jù)是再簡單不過了,我們只要用TOPPageSize就可以取出第一頁要顯示的記錄了。SELECT TOP PageSize QueryFields FROM TableName WHERE Condition ORDER BY PrimaryKey ASC(2) FirstIndex PageIndex (SELECT MAX(PrimaryKey) FROM (SELECT TOP PageSize*PageIndex PrimaryK

13、eyFROM TableNameWHERE ConditionORDER BY PrimaryKey ASC)TableA)WHERE ConditionORDER BY PrimaryKey ASC例如:PageIndex=1,紅- 黃- 藍(lán)PageindexIte midProductldPrice I0uni0011隼121020011$131030012ii300400122105oai3$14060013$12300700111$13OB001Z$154090013f 12aio0013$11(3) MiddleIndex PageIndex LastIndex接下來看看取數(shù)據(jù)庫表中

14、后半部分記錄的SQL語句。該語句跟前面的語句算法的原理是一樣的,只是方法稍微不同。先取出當(dāng)前頁之后的所有記錄的主鍵值,再從中選出最小值, 然后取出主鍵值小于該最小值的前PageSize條記錄。SELECT * FROM (SELECT TOP PageSize QueryFieldsFROM TableNameWHERE PrimaryKey (SELECT MIN(PrimaryKey) FROM (FROM TableNameWHERE ConditionORDER BY PrimaryKey DESC)TableA)WHERE ConditionORDER BY PrimaryKey D

15、ESC)TableBORDER BY PrimaryKey ASC之所以把取數(shù)據(jù)表前半部分記錄和取后半部分記錄的SQL語句分開寫,是因?yàn)槭褂萌∏鞍氩糠钟涗浀腟QL語句時(shí),當(dāng)前頁前面的記錄數(shù)目隨頁數(shù)遞增,而我們還要從這些記錄中取出它們的主鍵字段的值再從中選出最大值。這樣一來,分頁速度將隨著頁數(shù)的增加而減慢。因此我沒有這樣做,而是在當(dāng)前頁索引大于中間頁索引時(shí)( MiddleIndex 黃- 藍(lán)PageindexIte midProductldPrice0lioi0011$12020011$1310300121$13040012$11工0013$14060013$123CI070011$130840

16、90013f 12 100013Qi(4) PageIndex = LastIndex取最后一頁的記錄可以簡單地使用類似狀態(tài)(1)的做法:SELECT * FROM (SELECT TOP PageSize QueryFieldsFROM TableNameWHERE ConditionORDER BY PrimaryKey DESC)TableA ORDER BY PrimaryKey ASC不過,這樣產(chǎn)生的最后一頁不一定是實(shí)際意義上的最后一頁。因?yàn)樽詈笠豁摰挠涗洈?shù)未必剛好跟PageSize相等,而上面的 SQL語句是直接取得倒數(shù)的 PageSize條記錄。如果想 要精確地取得最后一頁的記錄

17、,應(yīng)該在先計(jì)算出該頁的記錄數(shù),作為TOP語句的條件:SELECT * FROM (SELECT TOP (RecordCount-PageSize*LastIndex) QueryFieldsFROM TableName WHERE ConditionORDER BY PrimaryKey DESC)TableA ORDER BY PrimaryKey ASC降序的SQL語句降序的SQL語句跟升序的大同小異,這里就不在羅嗦了J(1) PageIndex = FirstIndexSELECT TOP PageSize QueryFields FROM TableName WHERE Condit

18、ion ORDER BY PrimaryKey DESC(2) FirstIndex PageIndex = MiddleIndexSELECT TOP PageSize QueryFieldsFROM TableNameWHERE PrimaryKey (SELECT MIN(PrimaryKey) FROM (SELECT TOP PageSize*PageIndex PrimaryKeyFROM TableNameWHERE ConditionORDER BY PrimaryKey DESC)TableA)WHERE ConditionORDER BY PrimaryKey DESC(3

19、) MiddleIndex PageIndex (SELECT MAX(PrimaryKey) FROM (SELECT TOP (RecordCount-PageSize*(PageIndex+1) PrimaryKeyFROM TableNameWHERE ConditionORDER BY PrimaryKey ASC)TableA)WHERE ConditionORDER BY PrimaryKey ASC)TableB ORDER BY PrimaryKey DESCSELECT * FROM ( SELECT TOP (RecordCount-PageSize*LastIndex)

20、 QueryFieldsFROM TableName WHERE Condition ORDER BY PrimaryKey ASC)TableA ORDER BY PrimaryKey DESC如何動(dòng)態(tài)產(chǎn)生上述的 SQL語句?看了上面的SQL語句之后,相信大家已經(jīng)基本明白該分頁法的原理了。下面,我們將要設(shè)計(jì)一個(gè)動(dòng)態(tài)生成 SQL語句的類FastPaging 。該類有一個(gè)公有靜態(tài)方法,它根據(jù)您給出的 條件動(dòng)態(tài)生成SQL語句,作為方法的返回值。/產(chǎn)生根據(jù)指定字段排序并分頁查詢的SELECT語句。public static String Paging(int pageSize,/每頁要顯示的記錄的數(shù)

21、目。int pageIndex,/要顯示的頁的索引。int recordCount, String tableName, /String queryFields, /String primaryKey, / bool ascending, /String condition /)數(shù)據(jù)表中的記錄總數(shù)。要查詢的數(shù)據(jù)表。要查詢的字段。主鍵字段。是否為升序排列。查詢的篩選條件。StringBuilder sb = new StringBuilder();int pageCount = GetPageCount(recordCount,pageSize); /分頁的總數(shù)int middleIndex =

22、 GetMidPageIndex(pageCount); /中間頁的索引int firstIndex = 0; / 第一頁的索引int lastIndex = pageCount - 1; /最后一頁的索引if (pageIndex firstIndex & pageindex ().Append( SELECT MAX();elsesb.Append( = lastindex) /代碼略return sb.ToString();除了 Paging方法還有另外幾個(gè)方法:/根據(jù)記錄總數(shù)和分頁大小計(jì)算分頁數(shù)。public static int GetPageCount(int recordCoun

23、t, int pageSize) return (int)Math.Ceiling(double)recordCount/pageSize);/計(jì)算中間頁的頁索引。public static int GetMidPageIndex(int pageCount) return (int)Math.Ceiling(double)pageCount/2) - 1;/獲取排序白方式(ASC表示升序,DESC表示降序)public static String GetSortType(bool ascending) return (ascending ? ASC : DESC);/獲取一個(gè)布爾值,該值指示排序的方式是否為升序。public static bool IsAscending(String orderType) return (orderType.ToUpper() = DESC) ? false : true);讓DataGrid工作起來有了上面的類,實(shí)現(xiàn)分頁的工作就簡單多了。首先,我們要將DataGrid的AllowPaging屬性和AllowCustomPaging屬性為True ,除此之外,為了體現(xiàn)出升序和降序的功能,還需 要將AllowSorting 屬性也設(shè)置為True

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論