DataReader誰說不能作分頁?
看看這個範例,在 SQL指令上把分頁完成後,透過 DataReader來處理畫面,速度更快!
常來我 Blog的朋友,可能已經看過這篇文章了。
沒看過的話,就當作一篇廣告文吧.......
[廣告]老王賣瓜.....哪本ASP.NET的書值得你留下來?
這位同仁過了一年了,他最近又接到一個 ASP.NET的案子,
因為數據量大,客戶查詢的資料又 Join得亂七八糟
(大家都戲稱他們的報表,SQL指令寫得像篇小說一樣落落長)
所以,腦筋動到自己寫「分頁」上來了。
關於SQL指令作分頁,網路上文章很多。
我整理了幾篇文章,如下:
- 分頁從資料庫就做好 Row_number() T-SQL
- http://www.dotblogs.com.tw/mis2000lab/archive/2008/10/09/asp_paging_sql081009.aspx
- SQL指令(Select陳述句)的 ROW_NUMBER (資料來源:MSDN網站)
我的書本(上集)裡面,第十四章,收錄了很多常用的 ADO.NET程式。
Ch 14-4 裡面有自己撰寫 DataSet來作分頁的一個範例,包含每十頁作一個間隔
書本(上集) Ch 14章的兩個範例 -- Advanced_Page.aspx (傳統 DataSet的分頁)與 Advanced_Page_10_mis2000lab.aspx(每十頁作一個間隔)
可能這個範例比較沈悶,從來沒有讀者來信發問過。
這位同仁這次從書上找到這個範例,想要照本宣科一番。
但他又想使用 ROW_NUMBER來作。
想了一下,如果SQL指令的 Select陳述句已經透過 ROW_NUMBER作了分頁,
那何苦再透過 DataSet來作?
不如直接搭配 DataReader速度更快。
如此一來,也解決了 DataReader無法「分頁」的困擾(資料只能順向前進,不能回頭)
這主意真不錯!
不過,就像給貓掛鈴鐺。要叫誰去作?
(你當 RD不去 Coding,還來問我???)
以下就是我自己寫出來的成果,
詳細的解釋都在書本裡面囉。在此不贅述。
我個人簡單地測量三支程式(自己動手寫DataSet分頁),發現下面這個版本
DataReader + SQL指令(ROW_NUMBER)的速度最快,
比起書本(上集) Ch 14章 (Ch. 14-4)的兩個範例 -- Advanced_Page.aspx (傳統 DataSet的分頁)與
Advanced_Page_10_mis2000lab.aspx(每十頁作一個間隔)還快。
比他們快了 37%與 30%。
這應該要歸功於 StringBuilder與 DataReader吧。
上述兩個範例。
他們的寫法,跟以前的 ASP分頁程式都一樣,
只是改成 ASP.NET的語法,搭配 DataSet來作。
如果您是從 JSP / PHP / ASP升級上來的人,應該一看就會懂。
=======================================================================
Imports System.Data
Imports System.Data.SqlClient
Imports System.Text '-- StringBuilder需要用到
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim haveRec = False
Dim p As String = Request("p")
Dim Conn As SqlConnection = New SqlConnection("你的資料庫連結字串;MultipleActiveResultSets=True")
'-- 使用多重結果集(MARS)
Conn.Open()
Dim cmd As SqlCommand = New SqlCommand("select count(id) from test", Conn)
'---每頁展示 5筆資料
Dim PageSize As Integer = 5
Dim RecordCount As Integer = CType(cmd.ExecuteScalar().ToString, Integer)
cmd.Cancel()
If RecordCount = 0 Then
Response.Write("<h2>抱歉!無法找到您需要的資料!</h2>")
Conn.Close()
Response.End()
End If
Dim Pages As Integer = 0
Pages = ((RecordCount + PageSize) - 1) \ PageSize
If IsNumeric(Request("p")) Then
If Request("p") <> "" And CInt(Request("p")) > 0 And CInt(Request("p")) <= Pages Then
p = CInt(Request("p"))
Else
p = 1
End If
Else
p = 1
End If
Dim NowPageCount As Integer = 0
If (p > 0) Then
NowPageCount = (p - 1) * PageSize
End If
Response.Write("<h3>搜尋資料庫: (共計" & RecordCount & "筆 / 共需" & Pages & "頁)</h3>")
Response.Write("<hr width='97%' size='1'>")
Dim html_sb As New StringBuilder
'-- StringBuilder的用法,請參考 http://msdn2.microsoft.com/zh-tw/library/system.text.stringbuilder(VS.80).aspx
html_sb.Append("<table border=0 width='95%'>")
Dim dr As SqlDataReader = Nothing
'-- 註解: 2011/5/20,以下的程式略有修改。
Dim SqlStr As String = "Select test_time, id, title, summary
from (select ROW_NUMBER() OVER(ORDER BY id) AS 'RowNo', * from test) as t
where t.RowNo between @A and @B"
'==SQL指令的 ROW_NUMBER。參考資料: http://technet.microsoft.com/zh-tw/library/ms186734.aspx
Dim cmd1 As SqlCommand = New SqlCommand(SqlStr, Conn)
cmd1.Parameters.AddWithValue("@A", (NowPageCount+1) )
cmda.Parameters.AddWithValue("@B", (NowPageCount + PageSize))
dr = cmd1.ExecuteReader()
While (dr.Read())
haveRec = True
html_sb.Append("<tr><td WIDTH='12%' valign=top><font size='2' color=#800000>★(" & dr.Item("test_time").ToString() & ")</font></td>")
html_sb.Append("<td WIDTH='88%'><a href='Default_Disp.aspx?id=" & dr.Item("id").ToString() & "'><b>" & dr.Item("title").ToString() & "</b></a></td></tr>")
html_sb.Append("<tr><td WIDTH='12%'></td><td WIDTH='88%'><font color='#666666' size='2'>" & dr.Item("summary").ToString() & "</font></td></tr>")
html_sb.Append("<tr><td colspan='2' height='12'> </td></tr>")
End While
html_sb.Append("</table>")
If (haveRec) Then
Response.Write(html_sb.ToString())
If (Pages > 0) Then
Response.Write("<div align='center'>")
If (p > 1) Then
Response.Write("<a href='Advanced_Page_10_mis2000lab_DataReader_Row_Number.aspx?p=" & (p - 1) & "'>[<<<上一頁]</a>")
End If
Response.Write(" <b><a href='http://127.0.0.1/'>[首頁]</a></b> ")
If (p < Pages) Then
Response.Write("<a href='Advanced_Page_10_mis2000lab_DataReader_Row_Number.aspx?p=" & (p + 1) & "'>[下一頁>>>]</a>")
End If
'========= MIS2000 Lab.自製的「每十頁」一間隔,分頁功能=========start====
Response.Write("<hr width='97%' size=1>")
'== 這裡跟書本一樣,只需修改超連結的「檔案名稱」即可(請配合書本的範例,COPY上來即可)
'========= MIS2000 Lab.自製的「每十頁」一間隔,分頁功能=========end====
End If
End If
cmd1.Cancel()
dr.Close()
Conn.Close()
End Sub
=======================================================================
上面的 DataReader程式,大多來自於這個範本,
請您參考一下:http://www.dotblogs.com.tw/mis2000lab/archive/2008/04/24/3446.aspx
2014/7/17補充:
撰寫ADO.NET DataReader的分頁程式#2(搭配SQL 2012指令 OFFSET...FETCH)
這個程式最大的缺點就是「分頁的頁數」,透過 HTTP Get來傳遞,
必須注意 SQL Injection(資料隱碼)攻擊。
如果您可以改成 Session來傳遞頁數,那就安心多了。
2011/5/20補充:針對這個習題,我提供了一些變化。
簡單地說,在「第三步驟」,把資料呈現在畫面上。
我們在此使用 Repeater or ListView來呈現。
而不是自己一列一列慢慢寫程式的 While.....End While方式。這種作法主要是搭配美工人員的HTML。
請看:[習題]上集 Ch 14-4 (Repeater與 ListView版) -- 撰寫ADO.NET DataReader的分頁程式#2(搭配SQL指令 ROW_NUMBER)
這是給 書本 "上集" 的讀者,提供的補充習題。
如果您「第一次」看這種 ADO.NET程式覺得很困難,那是正常的,請不要灰心。
沒有人能不經學習,就能一次搞定。
只要有人、有書本帶著您走一遍,這都很簡單。
=== 最後要打一下廣告 ==========================
1. 如果您覺得我的描述、寫作方式,符合您的胃口。
2. 如果您看完以後,知道我寫書、介紹一些控制項或是技術........不是「混過去」、「帶過去」而已,而是真真確確地蒐集 "有用的範例",讓您學得更深入!
3. 如果您覺得:我出完書以後,還不定期地提供售後服務,提供補充教材......這樣的互動是 "良性"的,是值得鼓勵的。......已經推出 兩百多篇 補充範例了
4. 如果您(尤其是學生)真的想把基礎學好,而不是 "混"過這一門課就好、而不是寫個(畢業專題的)屍體出來交差(能畢業就好).....那麼.......
請您購買下面的書籍,
東西多到您學不完
上 / 下兩集,兩本書的厚度(我蒐集的各種範例)將近 兩千頁 !!......絕對不會讓您失望
我將思想傳授他人, 他人之所得,亦無損於我之所有;
猶如一人以我的燭火點燭,光亮與他同在,我卻不因此身處黑暗。----Thomas Jefferson
線上課程教學,遠距教學 (Web Form 約 51hr) https://dotblogs.com.tw/mis2000lab/2016/02/01/aspnet_online_learning_distance_education_VS2015
線上課程教學,遠距教學 (ASP.NET MVC 約 140hr) https://dotblogs.com.tw/mis2000lab/2018/08/14/ASPnet_MVC_Online_Learning_MIS2000Lab
寫信給我,不要私訊 -- mis2000lab (at) yahoo.com.tw 或 school (at) mis2000lab.net
(1) 第一天 ASP.NET MVC5 完整影片(5.5小時 / .NET 4.x版)免費試聽。影片 https://youtu.be/9spaHik87-A
(2) 第一天 ASP.NET Core MVC 完整影片(3小時 / .NET Core 6.0~8.0)免費試聽。影片 https://youtu.be/TSmwpT-Bx4I
[學員感言] mis2000lab課程評價 - ASP.NET MVC , WebForm 。 https://mis2000lab.medium.com/%E5%AD%B8%E5%93%A1%E6%84%9F%E8%A8%80-mis2000lab%E8%AA%B2%E7%A8%8B%E8%A9%95%E5%83%B9-asp-net-mvc-webform-77903ce9680b
ASP.NET遠距教學、線上課程(Web Form + MVC)。 第一天課程, "完整" 試聽。
......... facebook社團 https://www.facebook.com/mis2000lab ......................
......... YouTube (ASP.NET) 線上教學影片 https://www.youtube.com/channel/UC6IPPf6tvsNG8zX3u1LddvA/
Blog文章 "附的範例" 無法下載,請看 https://dotblogs.com.tw/mis2000lab/2016/03/14/2008_2015_mis2000lab_sample_download
請看我們的「售後服務」範圍(嚴格認定)。
......................................................................................................................................................
ASP.NET MVC => .NET Core MVC 線上教學 ...... 第一天課程 完整內容 "免費"讓您評估 / 試聽
[遠距教學、教學影片] ASP.NET (Web Form) 課程 上線了!MIS2000Lab.主講 事先錄好的影片,並非上課側錄! 觀看時,有如「一對一」面對面講課。