ASP.NET 網頁製作教本 – 從基本語法學起 第9章 ADO.NET 與資料庫存取(一)
9-1 ADO.NET 物件概述
ADO.NET 物件概述
ADO.NET 常用物件概述 (1)
ADO.NET常用物件概述 (2)
資料庫存取的過程
命名空間的引用 (1) ADO.NET 物件中,DataSet 物件附屬於System.Data 命名空間,若要在程式之中使用它,須先匯入 System.Data 命名空間,標示如下: <%@ Import Namespace="System.Data" %>
命名空間的引用 (2) 而Connection、Command、DataAdapter 及 DataReader 物件則附屬於System.Data.OleDb 或 System.Data.SqlClient,若要在程式中使用它們,須先匯入 System.Data.OleDb 或 System.Data.SqlClient 命名空間,標示如下: <%@ Import Namespace="System.Data.OleDb" %> <%@ Import Namespace="System.Data.SqlClient" %>
SqlClient 與 OleDb 的區別 System.Data.OleDb 是通用的資料庫存取物件,可用於存取 Access、SQL Server、dBase、Excel…等格式的資料庫,而System.Data.SqlClient 則是存取 SQL Server 資料庫專用的物件,在存取 SQL Server 資料庫方面有做過效能上的調整。 一般來說,若要存取 SQL Server 資料庫,應選用 System.Data.SqlClient 命名空間的物件,若要存取 SQL Server 以外的資料庫,則應選用 System.Data.OleDb 命名空間的物件。
類別名稱 (1) 實際的類別名稱如下:
類別名稱 (2) 宣告的敘述是有區別的 ' 使用System.Data.OleDb的物件 Dim conn As OleDbConnection Dim cmd As OleDbCommand Dim dr As OleDbDataReader Dim adp As OleDbDataAdapter ' 使用System.Data.SqlClient的物件 Dim conn As SqlConnection Dim cmd As SqlCommand Dim dr As SqlDataReader Dim adp As SqlDataAdapter
9-2 資料庫存取之路
路徑一: Connection - DataAdapter - DataSet - DataGrid 1.Connection 物件開啟 Sample.mdb 資料庫。 2. DataAdapter 物件開啟「成績單」資料表。 3.DataSet 物件存放「成績單」資料表。 4.DataGrid 控制元件顯示「成績單」資料表。 5.關閉 Sample.mdb 資料庫。
Route01.aspx 節錄 Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) ' 相關物件的宣告 Dim Conn As OleDbConnection ' 宣告一個 Connection 物件 Dim Adpt As OleDbDataAdapter ' 宣告一個 DataAdapter 物件 Dim Ds As DataSet ' 宣告一個 DataSet 物件
Route01.aspx 節錄 Part II ' Connection 物件開啟 Sample.mdb 資料庫 Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open() ' DataAdapter 物件開啟「成績單」資料表 Dim SQL = "Select * From 成績單" Adpt = New OleDbDataAdapter( SQL, Conn )
Route01.aspx 節錄 Part III ' DataSet物件存放「成績單」資料表 Ds = New Dataset() Adpt.Fill(Ds, "成績單") ' DataGrid控制元件顯示「成績單」資料表 MyGrid.DataSource = Ds.Tables( "成績單" ).DefaultView MyGrid.DataBind() ' 關閉Sample.mdb資料庫 Conn.Close() End Sub </script>
Route01.aspx
相關物件的宣告 (1) 以上程式共使用了四種物件 -- Connection、DataAdapter、DataSet及DataGrid,除了 DataGrid 會安插於 HTML 網頁之外,其他三個物件必須由程式來宣告,其敘述如下: Dim Conn As OleDbConnection ' 宣告一個 Connection 物件 Dim Adpt As OleDbDataAdapter ' 宣告一個 DataAdapter 物件 Dim Ds As DataSet ' 宣告一個 DataSet 物件
相關物件的宣告 (2) 由於以上的OleDbConnection、OleDbDataAdapter 及 DataSet 物件分別附屬於 System.Data.OldDb 及 System.Data,所以網頁的最前面還要增加「匯入命名空間」的標示,如下: <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %>
Connection 物件開啟 Sample.mdb 資料庫 此一階段所撰寫的程式如下: Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open()
DataAdapter 物件開啟「成績單」資料表 此一階段所撰寫的程式如下:
DataSet 物件存放「成績單」資料表 此一階段所撰寫的程式如下: Ds = New Dataset() Adpt.Fill(Ds, "成績單")
DataGrid 控制元件顯示「成績單」資料表 此一階段所撰寫的程式如下 MyGrid.DataSource = Ds.Tables( "成績單" ).DefaultView MyGrid.DataBind()
關閉 Sample.mdb 資料庫 此一階段所撰寫的程式只有一行: Conn.Close()
路徑二: Connection - Command - DataReade 1. Connection 物件開啟 Sample.mdb 資料庫。 2. Command 物件開啟「成績單」資料表。 3. DataReader 物件連結「成績單」資料表。 4. 利用 DataReader 物件逐欄逐列讀取資料表,然後填入輸出用的表格。 5. 關閉 Sample.mdb 資料庫。
Route02.aspx 節錄 Part I Sub Page_Load(sender As Object, e As EventArgs) ' 相關物件的宣告 Dim Conn As OleDbConnection ' 宣告一個 Connection 物件 Dim Cmd As OleDbCommand ' 宣告一個 Command 物件 Dim Rd As OleDbDataReader ' 宣告一個 DataReader 物件 ' Connection 物件開啟 Sample.mdb 資料庫 Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open()
Route02.aspx 節錄 Part II ' Command 物件開啟「成績單」資料表 Dim SQL = "Select * From 成績單" Cmd = New OleDbCommand( SQL, Conn ) ' DataReader 物件連結「成績單」資料表 Rd = Cmd.ExecuteReader() ' 利用DataReader物件逐欄逐列讀取資料表,然後填入輸出用的表格 OutputToTable( Rd ) ' 關閉 Sample.mdb 資料庫 Conn.Close() End Sub
Route02.aspx 節錄 Part III Sub OutputToTable( Rd As OleDbDataReader ) Dim I As Integer Dim row As TableRow Dim cell As TableCell ' 將資料表的「抬頭」填入表格中 row = New TableRow() row.BackColor = Drawing.Color.Yellow For I = 0 To Rd.FieldCount - 1 cell = New TableCell() cell.Text = Rd.GetName(I) row.Cells.Add( cell ) Next Table1.Rows.Add( row )
Route02.aspx 節錄 Part IV ' 逐列讀出資料表,然後填入表格中 While Rd.Read() row = New TableRow() For I = 0 To Rd.FieldCount - 1 cell = New TableCell() cell.Text = Rd.Item(I) row.Cells.Add( cell ) Next Table1.Rows.Add( row ) End While End Sub
Route02.aspx
Command 物件開啟「成績單」資料表
9-3 DataReader 物件
讀取資料表的抬頭
Reader01.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Dim Conn As OleDbConnection Dim Cmd As OleDbCommand Dim Rd As OleDbDataReader Dim I As Integer Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase )
Reader01.aspx Part II Conn.Open() Dim SQL = "Select * From 成績單" Cmd = New OleDbCommand( SQL, Conn ) Rd = Cmd.ExecuteReader() Msg.Text = "成績單:<UL>" For I = 0 To Rd.FieldCount - 1 Msg.Text &= "<LI>" & Rd.GetName(I) & "</LI>" Next Msg.Text &= "</UL>" Conn.Close() End Sub </script>
Reader01.aspx Part III <Html> <Body BgColor="White"> <HR></H3> <Form runat="server"> <asp:Label runat="server" id="Msg" /> </Form> <p> <HR></Body> </Html>
讀取資料表的所有資料列 利用 DataReader 物件依序讀取資料表的所有資料列,其程式架構大致如下: ‘ 每次讀取資料之前都要先呼叫 Read(),若含有資料,則傳回 True While DataReader.Read() ’ 利用 DataReader 物件所提供的屬性或方法讀取目前資料列 End While
Item 屬性(1) 在 While 迴圈中,讀取各欄位的資料時,會使用到 Item 屬性,Item 屬性可用來讀取某一欄位的內容,格式有兩種: DataReader.Item(欄位順序) DataReader.Item(欄位名稱)
Item 屬性(2) 以「成績單」資料表的第一筆資料為例,其內容如下:
Item 屬性(3) 而以下是讀取 Item 屬性的結果: DataReader.Item(0) 等於 850301 DataReader.Item(1) 等於 "陳桶一" DataReader.Item(2) 等於 90 DataReader.Item(3) 等於 76 DataReader.Item(4) 等於 98 DataReader.Item("學號") 等於 850301 DataReader.Item("姓名") 等於 "陳桶一" DataReader.Item("國文") 等於 90 DataReader.Item("英文") 等於 76 DataReader.Item("數學") 等於 98
Reader02.aspx
Reader02.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Dim Conn As OleDbConnection Dim Cmd As OleDbCommand Dim Rd As OleDbDataReader Dim I As Integer Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase )
Reader02.aspx Part II Conn.Open() Dim SQL = "Select * From 成績單" Cmd = New OleDbCommand( SQL, Conn ) Rd = Cmd.ExecuteReader() While Rd.Read() Msg.Text &= "<UL>" For I = 0 To Rd.FieldCount - 1 Msg.Text &= "<LI>" & Rd.GetName(I) & " = " & _ Rd.Item(I) & "</LI>" Next Msg.Text &= "</UL>" End While Conn.Close() End Sub </script>
Reader02.aspx Part III <Html> <Body BgColor="White"> <HR></H3> <Form runat="server"> <asp:Label runat="server" id="Msg" /> </Form> <p> <HR></Body> </Html>
讀取資料列的其他方法 除了 Iten 屬性之外,我們可能需要藉助以下屬性來讀取或判斷各欄位資料的內容:
GetDataTypeName 方法 (1) 讀取某一欄位的資料型別,以「成績單」資料表為例,各欄位的型別如下:
GetDataTypeName 方法 (2) 呼叫 GetDataTypeName 方法的傳回值如下:
GetOrdinal 方法 讀取某一欄位名稱對應的欄位編號,以「成績單」資料表為例,幾個欄位名稱對應的編號是「學號=0、姓名=1、國文=2、英文=3、數學=4」,所以: DataReader.GetOrdinal("學號") 傳回 0 DataReader.GetOrdinal("姓名") 傳回 1 DataReader.GetOrdinal("國文") 傳回 2 DataReader.GetOrdinal("英文") 傳回 3 DataReader.GetOrdinal("數學") 傳回 4
IsDbNull 方法 判斷某一欄位內容是否為 Null(沒有資料即為 Null) ,假設目前所讀取的資料中,每一個欄位都含有資料,則結果如下: DataReader.IsDbNull(0) 等於 False DataReader.IsDbNull(1) 等於 False DataReader.IsDbNull(2) 等於 False …
GetValues 方法(1) 讀取所有欄位的內容。Item屬性每次只能讀取一個欄位的資料,而 GetValues 方法則可以一次讀取所有欄位的資料,方法如下: ' 宣告一個陣列,而陣列元素的數目與欄位數相等 Dim Fields(DataReader.FieldCount-1) ' 讀取目前資料錄的所有欄位 DataReader.GetValues(Fields)
GetValues 方法(2) 以「成績單」資料表為例,若目前資料錄為第一筆,則執行以上程式之後,Fields 陣列將等於: Fields(0) = 850301 Fields(1) = "陳桶一" Fields(2) = 90 Fields(3) = 76 Fields(4) = 98
GetValues 方法(3) Reader03.aspx 節錄 Dim Fields(Rd.FieldCount-1) While Rd.Read() Rd.GetValues(Fields) Msg.Text &= "<UL>" For I = 0 To Rd.FieldCount - 1 Msg.Text &= "<LI>" & Rd.GetName(I) & " = " & _ Fields(I) & "</LI>" Next Msg.Text &= "</UL>" End While
將資料寫到 Table 控制元件中(1) Route02.aspx 網頁利用 DataReader 物件讀取資料,然後將資料填入 Table 控制元件中。 在 Route02.aspx 網頁中,插入 Table 控制元件的標示如下: <asp:Table runat="server" id="Table1" Border=1 CellPadding=2 CellSpacing=1 />
將資料寫到 Table 控制元件中(2) 讀取資料並將其填入 DataTable 控制元件的程式如下: #01 Sub OutputToTable( Rd As OleDbDataReader ) #02 Dim I As Integer #03 Dim row As TableRow #04 Dim cell As TableCell #05 #06 ' 將資料表的「抬頭」填入表格中 #07 row = New TableRow() #08 row.BackColor = Drawing.Color.Yellow
將資料寫到 Table 控制元件中(3) #09 For I = 0 To Rd.FieldCount - 1 #10 cell = New TableCell() #11 cell.Text = Rd.GetName(I) #12 row.Cells.Add( cell ) #13 Next #14 Table1.Rows.Add( row ) #15 #16 ' 逐列讀出資料表,然後填入表格中 #17 While Rd.Read() #18 row = New TableRow() #19 For I = 0 To Rd.FieldCount - 1 #20 cell = New TableCell() #21 cell.Text = Rd.Item(I) #22 row.Cells.Add( cell ) #23 Next #24 Table1.Rows.Add( row ) #25 End While #26 End Sub
將資料寫到 Table 控制元件中(4) Table 控制元件的物件結構
9-4 資料選取大師:Select 指令
資料選取大師:Select 指令 一、以 DataAdapter 物件開啟「成績單」資料表: Dim SQL = "Select * From 成績單" Adpt = New OleDbDataAdapter( SQL, Conn ) 二、 以 Command 物件開啟「成績單」資料表: Dim SQL = "Select * From 成績單" Cmd = New OleDbCommand( SQL, Conn )
基本句型一: Select 欄位串列 From 資料表 其中 * 表示「成績單」資料表所有欄位(包含「學號、姓名、國文、英文、數學」)所構成的串列,所以以上指令也等於:
欄位串列的規則 (1) 凡是資料表裡的欄位都可以成為「欄位 串列」的一員,例如: 欄位之順序可以自訂,不必與資料表裡 的欄位順序相同,例如: Select 姓名, 國文, 英文, 數學 From 成績單 (○) Select 姓名, 自然 From 成績單 (×) Select 姓名, 國文, 英文, 數學 From 成績單 (○) Select 姓名, 英文, 數學, 國文 From 成績單 (○)
欄位串列的規則 (2)
『欄位串列』的變化式 (1) 例如: 欄位名1 As 別名1, 欄位名2 As 別名2, … Select 股票代號 As ID, 股票名稱 As Stock From 股票行情表
『欄位串列』的變化式 (2) 以欄位名稱所組合出來的運算式也可以成為欄位串列的成員,例如: Select 學號, 姓名, 國文, 英文, 數學, 國文+英文+數學 As 總成績 From 成績單
如何測試 Select 指令?
基本句型二: Select...From...Where 篩選條件式
基本句型三: Select...From...Order By 欄位串列(1) 則執行結果如下:
基本句型三: Select...From...Order By 欄位串列(2) 則執行結果如下:
基本句型三: Select...From...Order By 欄位串列(3) 則執行結果如下:
基本句型三: Select...From...Order By 欄位串列(4) Order By 也可以與 Where 條件式結合,此時 Order By 必須放在 Where 條件式的後面,例如: Select * From 成績單 Where 國文 >= 60 Order By 國文 Desc
基本句型三: Select...From...Order By 欄位串列(5) 「Order By 欄位名稱」中的欄位名稱不 可以是欄位名稱的別名,例如以下的 SQL指令是錯誤的: 因為「總成績」不是成績單資料表中的 欄位,正確的寫法應該是: Select 學號, 國文+英文+數學 As 總成績 From 成績單 Order By 總成績 (×) Select 學號, 國文+英文+數學 As 總成績 From 成績單 Order By 國文+英文+數學 (○)
Select Top: 限定選取資料錄的筆數 在選取資料錄時,指定選取的最大筆數,減少 網路流量,如下: 另一種語法如下: 加了 Percent 保留字表示取百分比,假設「成 績單」資料表有 30 筆資料錄,則以上指令將 選取前 3 筆資料錄。 Select Top 10 * From 成績單 Order By 國文+英文+數學 Desc Select Top 10 Percent * From 成績單 Order By 國文+英文+數學 Desc
練習一 想要從 Sample.mdb 資料庫中選取符合以下條件資料錄,試寫出其 Select 指令: (1)股票行情表:成交量欄位大於等於 3500。 (2)股票行情表:漲跌欄位的絕對值大於 3。 (3)成績單:總成績(國文, 英文, 數學三個欄位的總和)大於 240。
練習二 完成以下 Select 指令: (1) 在Sample.mdb資料庫的「成績單」資料表中,希望被選取的資料錄按「數學」欄位遞增排序,如果「數學」欄位值相同,按「英文」欄位遞減排序。(2) 在 Sample.mdb 資料庫的「股票行情表」中,希望選取以下的資料錄, a. 漲幅前十名者(註:漲幅=漲跌/收盤價 %) b. 震盪幅度前十名者(註:震盪幅度=(最高價-最低價)/收盤價 %) c. 成交金額排行榜(遞減排序, 註:成交金額=收盤價×成交量)
「Where 條件式」變化式 -- 字串資料 在 Where 條件式中,字串資料可以放在 " " 裡面或是 ' '(單引號)裡面,例如:(選取「姓名」欄位等於「王為全」的資料錄) Select * From 成績單 Where 姓名 = '王為全' (正確) Select * From 成績單 Where 姓名 = "王為全" (正確)
「Where 條件式」變化式 -- 萬用字元 想選取所有「王××」同學的資料錄,那 麼該怎麼做呢? 想選取「姓名」欄位中含有 “小” 字的 資料錄,但 “小” 字不一定出現在欄位 的開頭位置,則 : Select * From 成績單 Where 姓名 Like '王%' Select * From 成績單 Where 姓名 Like '%小%'
「Where 條件式」變化式 -- % vs. _ “%” 代表 0~N 個字元,而 "_" 只能代表一個字元,例如: "DATA" Like "DAT_" 結果為True "DAT" Like "DAT_" 結果為False "DAT" Like "DAT%“ 結果為True "DATABASE" Like "DAT_" 結果為False "DATABASE" Like "DAT%" 結果為True
「Where條件式」變化式 -- P. 396 練習 想要從 Sample.mdb 資料庫中選取符合以下條件資料錄,試寫出其 Select 指令: (1)股票行情表:股票名稱等於「台塑」。 (2)股票行情表:股票名稱以「台」字開頭。 (3)股票行情表:股票名稱含有「台」字。 (4)股票行情表:股票名稱以「電」字結尾,且股票名稱只有兩個字。 (5)股票行情表:股票名稱以「中」開頭、以「銀行」結尾的。
Where 欄位名稱 Between 值一 And 值二 此一條件式的作用相當於: Where 欄位名稱 >= 值一 And 例如以下 SQL 指令表示選取數學成績介於 50 及 60 之間(包含 50 及 60)的資料錄: Select * From 成績單 Where 數學 Between 50 And 60
Where 欄位名稱 In (值一, 值二, …) 只要欄位的值屬於 (值一, 值二, …) 的集合,都符合條件,例如: Select * From 成績單 Where 姓名 In ('徐小噹', '劉一心', '林大鈺')
Where 欄位名稱 Is Null / Where 欄位名稱 Is Not Null 如果某一資料錄的某一欄位並未輸入任何資料,則此一欄位即為 Null 欄位,以上的條件式可以挑出某一欄位為 Null 或是非 Null 的資料錄。
VB 函數的使用 例如: 表示選取「姓名」欄位第二個字元等於 " 小" 的資料錄。 Select * From 成績單 Where Mid(姓名, 2, 1) = '小'
「Where條件式」變化式 -- P. 398 練習 想要從 Sample.mdb 資料庫中選取符合以下條件資料錄,試寫出其 Select 指令: (1)股票行情表:收盤價介於 100 及 200 之間。 (2)股票行情表:股票名稱等於「大陸」、「一銀」或「聯電」。 (3)股票行情表:股票名稱長度等於 3。
在程式中組合條件式 (1) 以下的例子是否正確: (1) V = 200 SQL = "Select * From 股票行情表 Where 收盤價 > V" Adpt = New OleDbDataAdapter( SQL, Conn ) (2) SQL = "Select * From 股票行情表 Where 收盤價 > " & V (3) SQL = "Select * From 股票行情表 Where 收盤價 > 200"
在程式中組合條件式 (2) 以下的例子是否正確: (5) V = "2301" SQL1 = "Select * From 股票行情表 Where 股票代號 = '" & V & "'" V = #07/02/1997# SQL2 = "Select * From 買賣記錄 Where 買賣日期 = #" & V & "#" (6) Select * From 股票行情表 Where 股票代號='2301' Select * From 買賣記錄 Where 買賣日期 = #1997/07/02#
9-5 再談 DataTable 物件
再談 DataTable 物件 Select 指令有哪些功能:
DataTable 物件與資料篩選(1) 想篩選資料,須設定 DataTable 的 DefaultView.RowFilter 屬性,例如要篩選 「國文及格」的資料列,則設定方法如 下: 結果 DataGrid 就只會顯示「國文及格」 的資料。 Ds.Tables("成績單").DefaultView.RowFilter = "國文 >= 60" MyGrid.DataSource = Ds.Tables("成績單").DefaultView MyGrid.DataBind()
DataTable 物件與資料篩選(2) RowFilter 屬性可接受的屬性值跟 Select指令的 Where 條件式相同,例如以下都是合法的篩選條件: “國文 < 60” 國文不及格的資料 "國文 < 60 Or 英文 < 60" 國文、英文其中一科不及格的資料 "國文 >= 80 And 數學 >= 90" 國文 >=80 且數學 >=90 的資料
Filter.aspx Filter.aspx 是一個利用 RowFilter 屬性來設定篩選條件的網頁:
Filter.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <Html> <Body BgColor="White"> <H3>Filter.aspx -- 使用 Default.RowFilter 篩選資料<HR></H3> <Form runat="server"> <asp:TextBox runat="Server" id="Filter" Size="40" /> (請輸入篩選條件)<Br> <asp:Button runat="server" Text="篩選" OnClick="Button_Click" /> <Blockquote>
Filter.aspx Part II <asp:DataGrid runat="server" id="MyGrid" AllowPaging="True" PageSize="10" OnPageIndexChanged="ChangePage" PagerStyle-HorizontalAlign="Right" PagerStyle-NextPageText="下一頁" PagerStyle-PrevPageText="上一頁" HeaderStyle-BackColor="#AAAADD" AlternatingItemStyle-BackColor="#FFFFC0" BorderColor="Black" CellPadding="2" CellSpacing="0" /><p> </Form> </Blockquote> <HR></Body> </Html>
Filter.aspx Part III <script Language="VB" runat="server"> Sub OpenDataBase_And_BindToDataGrid() Dim Conn As OleDbConnection Dim Adpt As OleDbDataAdapter Dim Ds As DataSet Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open() Dim SQL = "Select * From 成績單" Adpt = New OleDbDataAdapter( SQL, Conn )
Filter.aspx Part IV Ds = New Dataset() Adpt.Fill(Ds, "成績單") Ds.Tables("成績單").DefaultView.RowFilter = Filter.Text MyGrid.DataSource = Ds.Tables("成績單").DefaultView MyGrid.DataBind() Conn.Close() End Sub Sub Page_Load(sender As Object, e As EventArgs) If Not IsPostBack Then OpenDataBase_And_BindToDataGrid() End If
Filter.aspx Part V Sub Button_Click(sender As Object, e As EventArgs) OpenDataBase_And_BindToDataGrid() End Sub Sub SortPage(sender As Object, e As EventArgs) Sub ChangePage(sender As Object, e As DataGridPageChangedEventArgs) MyGrid.CurrentPageIndex = e.NewPageIndex </script>
DataTable 物件與新欄位的建立(1) DataTable 物件與資料列(DataRow 物件)的關係如下:
DataTable 物件與新欄位的建立(2) 每一個 DataRow 物件由多個資料項(Item)所組成,以「成績單」為例,每一個 DataRow 物件都含有「學號、姓名、國文、英文、數學、總成績」等 6個資料項,以第 I 個 DataRow 物件為例,各資料項分別表示成:
NewField.aspx
NewField.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Dim Conn As OleDbConnection Dim Adpt As OleDbDataAdapter Dim Ds As DataSet
NewField.aspx Part II Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open() Dim SQL = "Select * From 成績單" Adpt = New OleDbDataAdapter( SQL, Conn ) Ds = New Dataset() Adpt.Fill(Ds, "成績單") ' 建立「總成績」欄位 Dim I Dim Table1 As DataTable = Ds.Tables( "成績單" ) Table1.Columns.Add(New DataColumn("總成績", GetType(Integer)))
NewField.aspx Part III ' 逐列填入資料 For I = 0 To Table1.Rows.Count - 1 Dim 總成績 As Integer 總成績 = Table1.Rows(I).Item("國文") + _ Table1.Rows(I).Item("英文") + _ Table1.Rows(I).Item("數學") Table1.Rows(I).Item("總成績") = 總成績 Next MyGrid.DataSource = Table1.DefaultView MyGrid.DataBind() Conn.Close() End Sub </script>
NewField.aspx Part IV <Html> <Body BgColor="White"> <H3>NewField.aspx -- 利用 DataTable 物件建立「總成績」欄位 <HR></H3> <Center> <Form runat="server"> <asp:DataGrid runat="server" id="MyGrid" HeaderStyle-BackColor="#AAAADD" AlternatingItemStyle-BackColor="#FFFFC0" BorderColor="Black" CellPadding="2" CellSpacing="0" /> </Form> <p></Center> <HR></Body> </Html>
Select 指令與 DataTable 物件的抉擇
9-6 Repeater 與 DataList 控制元件
Repeater 與 DataList 控制元件(1) 希望以更自由的方式來展現資料,例如:
Repeater 與 DataList 控制元件(1) 對含有圖片的資料庫來說,採用非表格的方式來展現資料更有其必要性,例如:
Repeater 控制元件 使用 Repeater 的第一步 ,以Repeat1.aspx網頁為例 :
Repeat1.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <Html> <Body BgColor="White"> <H3>Repeater 控制元件與資料顯示<HR></H3> <Blockquote> <Form runat="server"> <asp:Repeater runat="server" id="MyRepeater"> <ItemTemplate> <B><%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>) </B>
Repeat1.aspx Part II <blockquote> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </blockquote> </ItemTemplate> </asp:Repeater> </Form> <p></Blockquote> <HR></Body> </Html>
Repeat1.aspx Part III <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Dim Conn As OleDbConnection Dim Adpt As OleDbDataAdapter Dim Ds As DataSet Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open()
Repeat1.aspx Part IV Dim SQL = "Select * From 成績單" Adpt = New OleDbDataAdapter( SQL, Conn ) Ds = New Dataset() Adpt.Fill(Ds, "成績單") MyRepeater.DataSource = Ds.Tables( "成績單" ).DefaultView MyRepeater.DataBind() Conn.Close() End Sub </script>
AlternatingItemTemplate 樣版 假設我們想要以「藍底白字」及「黑底白字」交叉顯示成績單資料,如下:
Repeat2.aspx Part I <asp:Repeater runat="server" id="MyRepeater"> <ItemTemplate> <p><Table Border="0" BgColor="Blue" Width="300"><Tr><Td> <Font Color="White"> <%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>)<Br> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </Font> </Td></Tr></Table> </ItemTemplate>
Repeat2.aspx Part II <AlternatingItemTemplate> <p><Table Border="0" BgColor="Black" Width="300"><Tr><Td> <Font Color="White"> <%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>)<Br> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </Font> </Td></Tr></Table> </AlternatingItemTemplate> </asp:Repeater>
SeparatorTemplate 樣版
Repeat3.aspx Part I <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <Html> <Body BgColor="White"> <H3>Repeat3.aspx -- 設定 SeparatorTemplate 樣版<HR></H3> <Blockquote> <Form runat="server"> <asp:Repeater runat="server" id="MyRepeater"> <ItemTemplate> <Table Border="0" Width="70%"><Tr> <Td width="160"> <Img Src='<%# Container.DataItem("相片") %>'> </Td>
Repeat3.aspx Part II <Td> 姓名: <%# Container.DataItem("姓名") %><br> 性別: <%# Container.DataItem("性別") %><br> 血型: <%# Container.DataItem("血型") %><br> 電話: <%# Container.DataItem("電話") %><br> 地址: <%# Container.DataItem("地址") %> </Td> </Tr></Table> </ItemTemplate> <SeparatorTemplate> <Hr Width="70%" Align="Left"> </SeparatorTemplate> </asp:Repeater> </Form> <p></Blockquote> <HR></Body> </Html>
Repeat3.aspx Part III <script Language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) Dim Conn As OleDbConnection Dim Adpt As OleDbDataAdapter Dim Ds As DataSet Dim Provider = "Provider=Microsoft.Jet.OLEDB.4.0" Dim Database = "Data Source=" & Server.MapPath( "Sample.mdb" ) Conn = New OleDbConnection( Provider & ";" & DataBase ) Conn.Open()
Repeat3.aspx Part IV Dim SQL = "Select * From 員工資料" Adpt = New OleDbDataAdapter( SQL, Conn ) Ds = New Dataset() Adpt.Fill(Ds, "員工資料") MyRepeater.DataSource = Ds.Tables( "員工資料" ).DefaultView MyRepeater.DataBind() Conn.Close() End Sub </script>
ItemTemplate 所定的格式 在 ItemTemplate 的定義中,將其顯示成以下格式:
使用 bar.gif 長條圖來分隔資料
使用 bar.gif 長條圖來分隔資料(2) 在 Repeat4.aspx 網頁中,SeparatorTemplate 樣版的定義如下: <SeparatorTemplate> <Img Src="bar.gif"> </SeparatorTemplate>
HeaderTemplate 及 FooterTemplate 樣版
Repeat5.aspx 節錄 Part I <ItemTemplate> <B><%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>) </B> <blockquote> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </blockquote> </ItemTemplate> <FooterTemplate> <Table Border="0" BgColor="Blue"><Tr><Td> <Font Color="White" Size="-1">☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆</Font> </Td></Tr></Table> </FooterTemplate>
Repeat5.aspx 節錄 Part II <ItemTemplate> <B><%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>) </B> <blockquote> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </blockquote> </ItemTemplate>
Repeat5.aspx 節錄 Part III <FooterTemplate> <Table Border="0" BgColor="Blue"><Tr><Td> <Font Color="White" Size="-1">☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆</Font> </Td></Tr></Table> </FooterTemplate> </asp:Repeater> </Form> <p></Blockquote> <HR></Body> </Html>
DataList 控制元件 雖然 DataList 是功能更完整的 Repeater 控制元件,但那並不表示 DataList 就可以完全取代Repeater 控制元件,為什麼呢? 不管是 DataList 或是 Repeater,資料輸出的格式都取決於樣版的定義,但 DataList 會將輸出的資料安排在 <Table>、<Tr> 及 <Td> 標示中,以表格形式來輸出,而 Repeater 則忠於樣版的定義,不會添加任何 HTML 標示。
Repeat1.aspx 的樣版定義 <B><%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>) </B> <blockquote> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </blockquote>
Repeat1.aspx 瀏覽之後 下傳的 HTML 碼 <B>陳桶一(850301) </B> <blockquote> 國文: 90, 英文: 76, 數學: 98 </blockquote> ...(以下略)
DList1.aspx 的樣版定義 <B><%# Container.DataItem("姓名") %>(<%# Container.DataItem("學號") %>) </B> <blockquote> 國文: <%# Container.DataItem("國文") %>, 英文: <%# Container.DataItem("英文") %>, 數學: <%# Container.DataItem("數學") %> </blockquote>
Dlist1.aspx 瀏覽之後 下傳的 HTML 碼 <table id="MyDataList" cellspacing="0" border="0" style="border-collapse:collapse;"> <tr> <td> <B>陳桶一(850301) </B> <blockquote> 國文: 90, 英文: 76, 數學: 98 </blockquote> </td> </tr><tr> <td> ...(以下略)
比較 Repeat1.aspx 及 Dlist.aspx (1) DataList 會藉助 <Table>、<Tr> 及 <Td> 標示來輸出資料,而 Repeater 則完全忠於樣版的定義,因為在某些場合下,使用與不使用 <Table>、<Tr> 及 <Td> 來輸出資料其結果將有所不同。
比較 Repeat1.aspx 及 Dlist.aspx (2)
設定單列資料筆數 對 Repeater 來說,每一列只能顯示一筆資料,但是對 DataList 來說,每一列卻可以顯示多筆資料。
讓 DataList 單列顯示多筆資料
Dlist4.aspx 節錄 Part I <asp:DataList id="MyDataList" runat="server" RepeatDirection="Horizontal" RepeatColumns="2" > <ItemTemplate> <Table><Tr> <Td> <Img Src='<%# Container.DataItem("相片") %>'> </Td>
Dlist4.aspx 節錄 Part II <Td> 姓名: <%# Container.DataItem("姓名") %><br> 性別: <%# Container.DataItem("性別") %><br> 血型: <%# Container.DataItem("血型") %><br> 電話: <%# Container.DataItem("電話") %><br> 地址: <%# Container.DataItem("地址") %> </Td> </Tr></Table> </ItemTemplate> </asp:DataList>
DataList 的 RepeatColumns 屬性 每一列顯示的資料筆數,本例將其設定成 "2",所以每一列將會顯示2筆資料。
DataList 的 RepeatDirection 屬性(1) 資料的排序方向,可以設定成 "Horizontal" 或 "Vertical"。 若設定成 “Horizontal”,則資料的排列先自左而右,然後再自上而下。 若設定成 “Vertical”,則資料的排列先自上而下,然後再自左而右。
DataList 的 RepeatDirection 屬性(2) 假設總共有10筆資料,而 RepeatColumns 屬性設定為 2、RepeatDirection 屬性設定為 "Horizontal",則排序結果如下:
DataList 的 RepeatDirection 屬性(3) 如果 RepeatColumns 屬性設定為 2、RepeatDirection 屬性設定為 "Vertical",則排序結果如下:
DataList 的 RepeatDirection 屬性(4)
設定 SelectedItemTemplate (被選項樣版)
設定 DataList 的外觀 (1) DataList 外觀的設定方法與 DataGrid 比較類似,以下圖為例:
設定 DataList 的外觀 (2) 所須設定的屬性如以下粗體字部分: <asp:DataList id="MyDataList" runat="server" Border="1" BorderColor="Black" CellPadding="2" CellSpacing="0" HeaderStyle-BackColor="#aaaadd" AlternatingItemStyle-BackColor="lightgray" SelectedItemStyle-BackColor="yellow" OnItemCommand="DataList_ItemCommand" >
設定 DataList 的樣版 - - HeaderTemplate 抬頭樣版,用以顯示 ,定義如下: <HeaderTemplate> 姓名(學號) </HeaderTemplate>
設定 DataList 的樣版 -- ItemTemplate 項目樣版,用以顯示資料表的每一筆資料,例如: 定義如下: <ItemTemplate> <%# Container.DataItem("姓名")%> (<%# Container.DataItem("學號")%>) <asp:LinkButton id="Detail" runat="server" Text="成績查詢"/> </ItemTemplate>
設定 DataList 的樣版 -- SelectedItemTemplate (1) 被選項樣版,用以顯示被選取的資料,定義如下: <SelectedItemTemplate> 姓名: <%# Container.DataItem("姓名")%><BR> 學號: <%# Container.DataItem("學號")%><BR> 國文: <%# Container.DataItem("國文")%><BR> 英文: <%# Container.DataItem("英文")%><BR> 數學: <%# Container.DataItem("數學")%><BR> <asp:LinkButton id="Title" runat="server" Text="關閉查詢"/> </SelectedItemTemplate>
設定 DataList 的樣版 -- SelectedItemTemplate (2) 而顯示出來的結果如下:
設定 DataList 的樣版 -- SelectedItemTemplate (3) (1) 插入 <asp:LinkButton> 控制元件,用途是關閉被選項,使其恢復成一般資料項。 (2) 背景顏色定義在 <asp:DataList> 控制元件的 SelectedItemStyle-BackColor 屬性中。 <asp:DataList id="DataList1" runat="server" Border="1" BorderColor="Black" CellPadding="2" CellSpacing="0" HeaderStyle-BackColor="#aaaadd" AlternatingItemStyle-BackColor="lightgray" SelectedItemStyle-BackColor="yellow" OnItemCommand="DataList_ItemCommand" >
處理「成績查詢」及「關閉查詢」連結 -- OnItemCommand 屬性 <asp:DataList> 的 OnItemCommand 屬性被設定為 “DataList_ItemCommand”,表示按下 <asp:DataList> 中的按鈕或連結時,將會啟動 DataList_ItemCommand 事件程序。
處理「成績查詢」及「關閉查詢」連結 -- 其連結的屬性設定值(1) 處理「成績查詢」及「關閉查詢」連結 -- 其連結的屬性設定值(1) <asp:LinkButton> 控制元件)的屬性設定中,「成績查詢」的Text屬性被設定成 "成績查詢"、「關閉查詢」的Text屬性被設定成 "關閉查詢",如下: <asp:LinkButton id="Detail" runat="server" Text="成績查詢"/> <asp:LinkButton id="Title" runat="server" Text="關閉查詢"/>
處理「成績查詢」及「關閉查詢」連結 -- 其連結的屬性設定值(2) 處理「成績查詢」及「關閉查詢」連結 -- 其連結的屬性設定值(2) 它們將成為 DataList_ItemCommand 事件程序用來判斷上網者按下的是「成績查詢」還是「關閉查詢」的根據。 Sub DataList_ItemCommand(sender As Object, e As DataListCommandEventArgs) If e.CommandSource.Text = "成績查詢" Then DataList1.SelectedIndex = e.Item.ItemIndex ElseIf e.CommandSource.Text = "關閉查詢" Then DataList1.SelectedIndex = -1 End If OpenDatabase_and_LinkToDataList() End Sub