[習題]上集 Ch 14-4 撰寫ADO.NET DataReader的分頁程式#1(搭配SQL指令 ROW_NUMBER)

DataReader誰說不能作分頁?
看看這個範例,在 SQL指令上把分頁完成後,透過 DataReader來處理畫面,速度更快!





 

常來我 Blog的朋友,可能已經看過這篇文章了。

沒看過的話,就當作一篇廣告文吧.......

[廣告]老王賣瓜.....哪本ASP.NET的書值得你留下來?


這位同仁過了一年了,他最近又接到一個 ASP.NET的案子,
因為數據量大,客戶查詢的資料又 Join得亂七八糟
(大家都戲稱他們的報表,SQL指令寫得像篇小說一樣落落長)

所以,腦筋動到自己寫「分頁」上來了。
關於SQL指令作分頁,網路上文章很多。

我整理了幾篇文章,如下:

 

我的書本(上集)裡面,第十四章,收錄了很多常用的 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,還來問我???crying

 

 

 



以下就是我自己寫出來的成果,
詳細的解釋都在書本裡面囉。在此不贅述。

我個人簡單地測量三支程式(自己動手寫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>搜尋資料庫:&nbsp;&nbsp; (共計" & 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("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b><a href='http://127.0.0.1/'>[首頁]</a></b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")

                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程式,大多來自於這個範本,

[ADO.NET] DataReader的標準範例 for ASP.NET (Code Behind版)

請您參考一下: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 49hr)  https://dotblogs.com.tw/mis2000lab/2016/02/01/aspnet_online_learning_distance_education_VS2015

線上課程,遠距教學 (ASP.NET MVC 75hr)  https://dotblogs.com.tw/mis2000lab/2018/08/14/ASPnet_MVC_Online_Learning_MIS2000Lab

ASP.NET MVC線上課程 第一天 免費看 (5.5小時) 

寫信給我,不要私訊 --  mis2000lab (at) yahoo.com.台灣  或  school (at) mis2000lab.net


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 (Web Form) 課程 上線了!MIS2000Lab.主講

事先錄製好的影片,並非上課時側錄!   觀看影片時,有如我「一對一」跟您面對面講課

 

ASP.NET MVC 5 線上教學

累積時數約 75小時...... 第一天(5.5小時)完整內容,"免費"讓您評估