Rockford Lhotka
Magenic Technologies
2004年9月1 日
從 MSDN Code Center 下載 vbADO.exe 示例文件(英文)。
Microsoft .NET 包括一種新的數據訪問技術,稱為 ADO.NET。采用這種新技術的原因有很多,其中包括:對斷開連接的數據的內部支持、全面的 XML 支持以及該技術與整個 .NET 框架的無縫整合。
本文著重討論該技術包含哪些功能,以及如何充分利用這一技術來使用數據庫。我們首先介紹連接到數據庫的基本要素,然后討論如何讀取和寫入數據庫。ADO.NET 的內容十分廣泛,針對每種操作提供了很多方法。在本文中,我們將使用 DataSet 對象讀取和寫入數據,并嘗試使用 DataReader 和 Command 對象手動讀取和寫入數據。同時還將探索動態 SQL 和存儲過程的使用。讀完本文后,您將可以使用 ADO.NET 來創建、讀取、更新和刪除數據。
大多數 Visual Basic® .NET 項目類型都自動引用 ADO.NET,包括 Windows® 應用程序、ASP.NET Web 應用程序和類庫項目。此外,在這些項目類型的某個項目級別上,還會自動導入 System.Data 命名空間。您可以在項目的 Property(屬性)對話框中看到全局 Import 語句列表。
圖 1:顯示在項目 Property(屬性)對話框中的項目級導入
System.Data 命名空間對應用程序提供基本的數據支持,主要著重于數據的使用而不是數據訪問本身。這意味著,在默認情況下,我們可以訪問 DataSet 對象及其相關子對象,也可以訪問定義如何進行數據訪問的基本界面。
但是,在能夠與數據庫進行交互之前,我們需要確定要使用的數據提供程序。Microsoft .NET 包括兩個現成的數據提供程序。SQL Server 提供程序提供對 Microsoft SQL Server™ 7.0 或更高版本的優化訪問。OleDb 提供程序提供對具有 OleDb 提供程序的所有數據庫的訪問。
SQL Server 提供程序位于 System.Data.SqlClient 命名空間。該提供程序針對 SQL Server 訪問進行了優化,與通過 OLE DB 使用 ADO 相比,它能夠提供更好的性能。此外,該提供程序還具有一個智能連接緩沖池機制,因此,與它的前任 OLE DB 或 ODBC 相比,能夠提供更快的緩沖數據庫連接訪問。
OleDb 提供程序位于 System.Data.OleDb 命名空間。使用此提供程序,我們可以通過 OLE DB 與數據庫進行交互。任何包含現有 OLE DB 提供程序的數據庫都可以通過 .NET 中的 OleDb 提供程序進行訪問。
還有一種 Odbc 提供程序,您可以從 MSDN 下載該程序。它是 ODBC 的包裝程序,允許您與任何具有 ODBC 驅動程序的數據庫進行交互。
連接到數據庫
數據庫連接由用于數據庫的提供程序進行處理。所有提供程序都會提供一個連接對象。SQL 提供程序包含 SqlConnection 對象,而 OleDb 提供程序包含 OleDbConnection 對象。這兩種連接對象都使用連接字符串和其他信息(如安全憑據)來定義數據庫的位置。
OleDbConnection 使用普通的 OLE DB 連接字符串,這并不奇怪,因為它只是將字符串傳遞給基礎 OLE DB 提供程序。下面是用于 Access 數據庫的 OleDbConnection 字符串示例:
Provider=Microsoft.Jet.OLEDB.4.0;Password="";User ID=Admin;Data Source=grocertogo.mdb
SqlConnection 使用類似的連接字符串,但不需要數據庫提供程序,而只需要有關如何查找數據庫的信息和安全憑據。下面是 SQL Server 的 Pubs 數據庫的示例:
data source=localhost;initial catalog=pubs;user id=sa;password=
在許多情況下,甚至在手動創建連接對象時,我們也不必擔心如何創建自己的連接字符串。Visual Studio® .NET IDE 包含的功能使我們無需鍵入任何代碼行,即可輕松地添加和配置連接。
在工具箱中,您可以找到 Data(數據)選項卡,其中包括常見的數據對象,例如 DataSet、OleDbConnection 和 SqlConnection 對象。您可以將這些對象拖放到 Windows 窗體、Web 窗體或組件設計器中。
圖 2:工具箱中的 Data(數據)選項卡包含常見的數據對象
這些對象為非圖形實體,因此不會直接顯示在窗體上,而是顯示在設計器底部的圖標欄中,以便于用戶訪問。這些實體在很多方面都與控件類似,因此當單擊這些實體時,您可以使用普通的 Properties(屬性)窗口更改它們的屬性和設置。
例如,我們創建一個名為 ADO 的 Windows 應用程序,并將一個 SqlConnection 對象拖放到窗體中。該對象將出現在控件圖標欄中。然后,可以使用 Properties(屬性)窗口將其名稱更改為一個更具說明性的名稱,例如 cnPubs。
圖 3:添加到 Windows 窗體的 SqlConnection 對象
向導是一個更加有用的工具,它可以幫助我們構造連接字符串。在 Properties(屬性)窗口中單擊 ConnectionString 字段,然后單擊該字段中顯示的下箭頭。其中將列出為該控件定義的所有連接以及一個 <New Connection...>(<新建連接...>)條目。
如果單擊 <New Connection...>(<新建連接...>)條目,Visual Studio .NET 將顯示一個對話框以定義數據源。
單擊 OleDbConnection 對象將顯示標準的 OLE DB 連接對話框,您可以從中選擇 OLE DB 數據提供程序,并指定該提供程序所需的全部信息。單擊 SqlConnection 對象將顯示一個對話框,您可以從中選擇 SQL Server、定義安全設置以及選擇該服務器上的數據庫。
這里,我們設置一個指向本地計算機上的 Pubs 數據庫的連接,在后面的示例中將使用該連接。cnPubs 的設置存放在窗體中由 Windows 窗體設計器生成的代碼區域中,默認情況下,這些設置被隱藏。這與窗體中的其他控件沒有什么不同。
您也可以選擇手動配置連接對象。為此,需要使用類似如下的代碼:
Dim cnPubs As New SqlConnection() cnPubs.ConnectionString = _ "data source=localhost;initial catalog=pubs;integrated security=SSPI"
這些基本代碼與設計器為我們創建的基本代碼相同。
打開和關閉連接
請注意,無論使用設計器還是手動代碼,都只是定義了連接,而并未打開連接。我們對何時打開和關閉連接擁有完全的控制權,因此可以在應用程序中進行最有效的操作。
請記住,SqlClient 會緩沖數據庫連接,因此,作為一般原則,最好將系統設計為打開連接、使用連接,并在完成操作后立即關閉連接。使用 OleDb 客戶端時,對于用于您的數據庫的特定 OLE DB 提供程序,您需要遵循某些最佳的實踐經驗。
使用正確的錯誤處理以確保數據庫連接始終被關閉(即便出現錯誤時),這一點非常重要。使用數據庫連接時,建議采用以下結構:
Try cnPubs.Open() Try ' 此處進行數據訪問 Finally cnPubs.Close() End Try Catch ' 此處處理數據訪問錯誤 End Try
外層的 Try..Catch 塊允許您處理可能發生的任何數據訪問錯誤,包括無法打開連接,以及在讀取或更新數據時可能發生的任何錯誤。
內層的 Try..Finally 塊可以確保即使在讀取或更新數據時確實發生錯誤的情況下,連接仍然被關閉。Finally 構造不會重置錯誤,因此所有錯誤都將由外層的 Catch 構造捕獲。但是,不論是否發生錯誤,都將運行 Finally 塊,從而確保正確關閉連接。
其實許多情況下都不需要此結構,因為我們即將使用的其他 ADO.NET 對象通常會自動打開或關閉連接。一般來講,針對您編寫的大量額外的數據訪問代碼,ADO.NET 很可能可以通過其他對象或方法提供更簡單的解決方案。
使用數據
我們已經知道了如何定義、打開和關閉數據庫連接,下面我們將通過讀取和寫入數據庫來使用數據。
數據庫交互最終是通過 Command 對象來完成的,盡管這些對象可能隱藏在其他更為抽象的對象后面。Command 對象包含有關如何讀取或更新數據庫中的數據的指令。這些指令可能是動態 SQL 語句,也可能是調用存儲過程所需的信息。
讀取數據通常有兩種方法。其一是 DataSet 對象,它提供一個我們可以使用的、抽象的、斷開連接的數據副本。DataSet 由 DataAdapter 對象填充,DataAdapter 對象又與基礎 Command 和 Connection 對象進行交互。
DataAdapter 使用一個名為 DataReader 的對象從數據庫中實際獲取數據。然后,這些數據將被用來填充 DataSet 對象。
圖 4:由 DataAdapter 加載的 DataSet
第二種讀取數據的方法是直接使用 DataReader,從而繞過整個 DataSet 和 DataAdapter 技術。這種方法在創建 Web 頁或 XML Web Services 時尤為有用,因為我們通常只是從數據庫中提取數據,然后簡單地將其復制到頁面或 XML 輸出結果中。將數據復制到 DataSet,然后再將其復制到頁面或 XML 結果需要花費額外的時間。
圖 5:直接調用 Command 對象獲取 DataReader
盡管這種手動方法有時比較快,但與使用 DataAdapter 和 DataSet 相比,它需要我們做更多事情。
DataSet 和 DataAdapter 對象還提供了更新數據的機制。DataAdapter 不僅包含檢索數據的 Command 對象,還包含插入、更新和刪除數據的 Command 對象。您只需將已更改的 DataSet 對象傳遞到 DataAdapter,后者將自動調用相應的 Command 對象將更改更新到數據庫中。
默認情況下,此更新進程使用優化的并發處理,也就是說,進行更新之前將檢查基礎數據。如果用戶更改了數據,則不會應用更新,并將通知代碼發生了沖突。您可以禁用這種行為,以免盲目地將更新寫入數據庫,而不管其他用戶所做的更改。
此外,您也可以選擇通過直接調用 Command 對象(其中包含更新數據庫所需的指令)手動更新數據庫。在這種情況下,我們需要處理任何并發問題。
使用 DataSet 讀取和更新數據
DataSet 是保存在內存中供您使用的斷開連接的數據副本。要從數據提供程序中填充 DataSet,我們需要使用 DataAdapter 對象,該對象將使用 Command 對象生成 DataReader,然后可以從 DataReader 中將數據讀入 DataSet。
創建和配置 DataSet 的方法有很多,最簡單的方法是使用 Visual Studio .NET。您也可以手動配置 DataSet,但是就象處理連接對象一樣,您所編寫的代碼與 Visual Studio .NET 自動生成的代碼效果一樣。
有趣的是,通過 Visual Studio .NET 創建 DataSet 其實是這樣一個過程,即創建 DataAdapter 對象,然后讓 DataAdapter 對象自動生成 DataSet。
從工具箱的 OleDb 選項卡將 SqlDataAdapter 對象拖放到窗體中。這將啟動向導。
首先顯示說明面板,然后,向導的下一個面板將詢問要使用的連接對象。我們只有一個連接,因此很容易選擇。請注意,您也可以從此面板創建一個連接,然后使用 DataAdapter 開始整個過程,這樣便可以通過此向導指導您完成整個過程。
在下一個面板中,要執行的任務就比較復雜了。請記住,DataAdapter 實際上是由四個 Command 對象組成的集合。在此面板中,您需要定義如何配置這些 Command 對象。它們可以使用動態 SQL 語句,可以調用數據庫中現有的存儲過程,也可以由向導自動創建新的存儲過程。當然,最后一個選項要求您具有向數據庫中添加存儲過程的安全訪問權限。
下一個面板取決于所選擇的選項。如果選擇使用 SQL 語句或創建新的存儲過程,您可以輸入 SELECT 語句或使用查詢生成器構建一個存儲過程。執行插入、更新和刪除操作的其他三個命令將基于 SELECT 語句自動構建。
如果選擇現有的存儲過程,下一個面板將允許您選擇四個存儲過程以分別與四個命令相關聯。
在本示例中,我們使用包含 SELECT 語句的 SQL 語句,如下所示:
SELECT au_id, au_lname, au_fname FROM Authors
向導的最后一個面板只是確認我們指定的操作。單擊 Finish(完成)后,用于配置 DataAdapter 的代碼將被保存到窗體或其他設計器的隱藏代碼區域。
在 Properties(屬性)窗口中,將 DataAdapter 對象的名稱更改為 daAuthors,因為它被配置為與 authors 表一起使用。
您可以右擊控件圖標欄中的 DataAdapter,然后選擇 Configure Data Adapter(配置數據適配器)選項,從而隨時更改這些選項。
您也可以右擊控件并選擇 Generate Dataset(生成數據集),使 DataAdapter 自動創建代表數據的 DataSet 對象。這是配置 DataSet 對象的最簡單的方法,我們將采用此方法。
這將顯示一個對話框,您可以從中將 DataAdapter 與現有的 DataSet 相關聯,或者創建一個新的 DataSet。在本示例中,我們將創建一個名為 dsPubs 的新 DataSet。
單擊 OK(確定),即可創建 DataSet。一個名為 dsPubs1.xsd 的新文件將添加到項目中,一個名為 dsPubs1 的新控件將添加到控件圖標欄中。
xsd 文件是一個 XML 架構文件,用于定義控件所保持的數據結構。該架構是根據 DataAdapter 對象中的 SELECT 語句或存儲過程自動生成的。
單擊 dsPubs1 控件,然后在 Properties(屬性)窗口中將其名稱更改為 dsPubs。該控件就是我們的 DataSet,它現在已經準備就緒,可以通過編程方式或數據綁定使用 DataAdapter 中的數據了。
在窗體中添加一個 DataGrid 和兩個按鈕,如圖 6 所示。
圖 6:在窗體中添加 DataGrid 和兩個按鈕
選擇 DataGrid,然后使用 Properties(屬性)窗口將其 DataSource 屬性設置為 dsPubs.Authors。這會將網格綁定到 DataSet,并會使網格立即顯示正確的列名稱。由于項目中已添加 xsd 架構文件,因此所有數據都可用。
剩下的工作只是添加一些代碼,使用 DataAdapter 來加載 DataSet。在 Refresh data(刷新數據)按鈕后面添加此代碼:
Private Sub btnRefresh_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnRefresh.Click daAuthors.Fill(DsPubs.authors) End Sub
請注意,這里我們沒有打開或關閉連接。因為 DataAdapter 可以為我們自動完成此操作。它可以打開連接,獲取數據并關閉連接,而無需我們額外編寫任何代碼。
同樣,我們可以在 Save Changes(保存更改)按鈕后面添加代碼以更新數據:
Private Sub btnSave_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSave.Click daAuthors.Update(DsPubs.authors) End Sub
由于 DataAdapter 包含可以執行插入、更新和刪除操作的 Command 對象,因此只需調用 Update 方法便可以自動完成所有任務。DataSet 本身會跟蹤每行數據是否被更改、插入或刪除,因此這一技術只會將更改過的數據更新到數據庫中。
由于網格被綁定到 DataSet,當我們運行該應用程序并單擊 Refresh(刷新)按鈕時,將顯示數據,并且可以編輯這些數據。僅在單擊 Save Changes(保存更改)按鈕后,更改才會保存到數據庫中。
這顯示了 DataAdapter 和 DataSet 對象的強大功能,同時也說明了我們對 .NET 中的數據綁定的控制能力。
此外我們還應意識到,這里所使用的 DataSet 是非常簡單的。實際上,DataSet 可以同時支持多個表,并且可以知道這些表之間的關系,這有助于加強關系規則以及導航數據。DataSet 是完全斷開連接的,也就是說,可以通過網絡將其傳遞到遠程客戶端,而遠程客戶端又可以將其返回到服務器(從中可以使用 DataAdapter 將更改更新到數據庫中)。
手動讀取和更新數據
盡管 DataSet 和 DataAdapter 非常簡單,也非常好用,但它們并非在任何時候都是最佳選擇。有時候,我們需要快速讀取數據,并且不需要在內存中存儲數據副本。還有些時候,我們要更新到數據庫中的數據可能不是來自 DataSet,或者在將數據更新到數據庫之前,不適于使用 DataSet 將數據放在內存中。
讀取數據時,我們可能只需找到數據并將其發送到其他位置,例如 Web 頁、XML 文檔或文本文件。在這些情況下,直接使用 DataReader 對象會更有效。
為解釋其工作方式,我們將數據復制到文本文件中。在窗體中添加另一個按鈕,并命名為 btnCopyToFile。然后添加以下代碼:
Private Sub btnCopyToFile_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnCopyToFile.Click Dim cn As New SqlConnection() Dim cm As New SqlCommand() cn.ConnectionString = _ "data source=localhost;initial catalog=pubs;integrated security=SSPI" Try cn.Open() Try cm.Connection = cn cm.CommandText = "SELECT au_id,au_fname,au_lname FROM authors" ' 此處進行數據處理 Finally cn.Close() End Try Catch ex As Exception MsgBox(ex.ToString) End Try End Sub
這是我們前面討論過的代碼結構,它將打開和關閉 Connection 對象的操作包含在嵌套的 Try 塊中,以確保無論發生什么錯誤,都可以關閉連接。請注意,我們配置了一個 Command 對象,以使用 SQL 語句從 authors 表中選擇數據。這里,我們直接使用 Command 對象,而不是將其嵌入到 DataAdapter 中。
現在,我們可以創建一個 DataReader,它可以按照 Command 對象的指示從數據庫中檢索數據:
Dim cn As New SqlConnection() Dim cm As New SqlCommand()Dim dr As SqlDataReader
cn.ConnectionString = _ "data source=localhost;initial catalog=pubs;integrated security=SSPI" Try cn.Open() Try cm.Connection = cn cm.CommandText = "SELECT au_id,au_fname,au_lname FROM authors"dr = cm.ExecuteReader()
Try
While dr.Read
' 此處處理每行數據End While
Finally
dr.Close()
End Try
Finally cn.Close() End Try
使用 DataReader 非常直截了當。Command 對象上的 ExecuteReader 方法使 Command 可以對數據庫運行,并返回一個 DataReader 對象作為結果。
DataReader 對象包含一個 Read 方法,使對象可以逐行讀取數據。它從 BOF(文件開始處)開始,而 BOF 不是有效行,因此在嘗試讀取任何數據之前,我們需要先調用一次 Read 方法。Read 方法返回一個布爾值。如果返回 False,則表明沒有可供讀取的數據。
DataReader 包含在 Try..Finally 塊中,因此我們可以確保完成操作時可以正確將其關閉。這一點非常重要,因為只有當 DataReader 關閉后,Connection 對象才可以用于其他操作。
某些數據也要在 DataReader 關閉后才可用。例如,記錄計數值 RecordsAffected 只有在 DataReader 關閉后才能確保準確性。如果使用存儲過程作為 Command,則只有在 DataReader 關閉后,輸出參數值才可用。
現在,剩下的工作就是添加代碼,將數據從 DataReader 寫入文本文件:
Dim outfile As StreamWriter
Tryoutfile = File.CreateText("c:\authors.txt")
While dr.ReadWith outfile
.Write(dr("au_id"))
.Write(",")
.Write(dr("au_lname"))
.Write(",")
.Write(dr("au_fname"))
.WriteLine()
End With
End While Finallyoutfile.Close()
dr.Close() End Try
這里使用了列名稱在行中建立索引,以檢索每一列。您也可以使用數字索引,從零開始累計列數?梢允褂 FieldCount 方法返回行中的列數。
還有一種更好的方法,即同時使用數字索引和 DataReader 的特定類型方法來檢索每個字段。上面的代碼使用了后期綁定,并且不是特定于類型的,因而執行速度較慢。實際上,這里每個數據元素都作為 Object 類型返回,從而必須將其轉換為相應的類型才能使用。
我們可以使用諸如 GetString 和 GetInteger 等方法,它們將以早期綁定和特定類型的方式返回數據。為此,可以編寫如下代碼:
With outfile
.Write(dr.GetString(0))
.Write(",")
.Write(dr.GetString(1))
.Write(",")
.Write(dr.GetString(2))
.WriteLine()
End With
DataReader 包括每種數據類型的方法,您可以根據需要檢索數據。如果嘗試使用錯誤的類型方法檢索數據,將會收到運行時錯誤。例如,嘗試使用 GetString 檢索 Integer 將導致錯誤。顯然,使用字段名可以提高可讀性,而使用數字索引連同特定類型方法可以提高性能。
遍歷所有數據之后,關閉文本文件。請注意,該文件也包含在 Finally 塊中,因此,我們可以確保即使處理數據時發生錯誤,文件也可以關閉。
我們也可以直接調用 Command 對象手動更新數據。如果要更新的數據不是存儲在 DataSet 中,則可以使用此方法。在本示例中,我們從文本文件中讀回數據,并更新數據庫。
在窗體中添加一個名為 btnFileToDb 的按鈕,其代碼如下:
Private Sub btnFileToDb_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnFileToDb.Click Dim cn As New SqlConnection() Dim cm As New SqlCommand() Dim infile As StreamReader cn.ConnectionString = _ "data source=localhost;initial catalog=pubs;integrated security=SSPI" infile = File.OpenText("c:\authors.txt") Try cn.Open() Try Dim instr As String Dim indata() As String cm.Connection = cn cm.CommandText = "UPDATE authors " & _ "SET au_fname=@fname,au_lname=@lname " & _ "WHERE au_id=@id" cm.Parameters.Add(New SqlParameter("@id", SqlDbType.VarChar)) cm.Parameters.Add(New SqlParameter("@fname", SqlDbType.VarChar)) cm.Parameters.Add(New SqlParameter("@lname", SqlDbType.VarChar)) While infile.Peek > -1 instr = infile.ReadLine Debug.WriteLine(instr) indata = Split(instr, ",") cm.Parameters("@id").Value = indata(0) cm.Parameters("@lname").Value = indata(1) cm.Parameters("@fname").Value = indata(2) cm.ExecuteNonQuery() End While Finally cn.Close() End Try Catch ex As Exception MsgBox(ex.ToString) Finally infile.Close() End Try End Sub
同樣,我們采用相同的錯誤處理基本結構,以確保在完成操作之后,文件和數據庫連接都被關閉。
代碼中令人感興趣的是我們配置 Command 對象的位置:
cm.Connection = cn cm.CommandText = "UPDATE authors " & _ "SET au_fname=@fname,au_lname=@lname " & _ "WHERE au_id=@id" cm.Parameters.Add("@id", SqlDbType.VarChar) cm.Parameters.Add("@fname", SqlDbType.VarChar) cm.Parameters.Add("@lname", SqlDbType.VarChar)
由于要在循環中使用此對象,我們使用參數對其進行了預配置。這與用來調用接受參數的存儲過程的基本機制相同。
將 Command 對象配置為根據參數更新數據后,我們可以遍歷文本文件,分析每行文本并對每行執行 Command 對象:
While infile.Peek > -1 instr = infile.ReadLine Debug.WriteLine(instr) indata = Split(instr, ",") cm.Parameters("@id").Value = indata(0) cm.Parameters("@lname").Value = indata(1) cm.Parameters("@fname").Value = indata(2) cm.ExecuteNonQuery() End While
上述代碼說明了如何執行 Command 對象進行插入、更新或刪除操作,同時也說明了如何使用 StreamReader 類輕松讀取和分析以逗號分隔的文本文件的內容。
調用存儲過程
我們已經知道如何使用 DataAdapter 來調用 Command 對象,或者如何使用 SQL 語句直接與數據庫進行交互。Command 對象還可用于調用存儲過程,這通常是數據庫交互的首選方法,因為與動態 SQL 語句相比,存儲過程通常能夠提供更好的性能。
假設 Pubs 數據庫包括一個檢索作者數據的存儲過程:
CREATE PROCEDURE getAuthors AS SELECT au_id,au_fname,au_lname FROM authors RETURN
我們可以更改 btnCopyToFile 的代碼,以使用此存儲過程而不是動態 SQL 語句。代碼如下所示:
cm.Connection = cncm.CommandType = CommandType.StoredProcedure
cm.CommandText = "getAuthors"
CommandType 屬性被更改為調用存儲過程;CommandText 屬性提供了存儲過程的名稱,而不是 SQL 語句本身。
可以使用存儲過程來處理更新,例如:
CREATE PROCEDURE updateAuthor ( @id varchar(11), @fname varchar(20), @lname varchar(40) ) AS UPDATE authors SET au_fname=@fname, au_lname=@lname WHERE au_id=@id RETURN
在本示例中,可以更改 btnFileToDb 的代碼以使用存儲過程:
cm.Connection = cncm.CommandType = CommandType.StoredProcedure
cm.CommandText = "updateAuthor"
這一更改非常容易,因為我們已經在 SQL 語句中使用了參數,代碼已經被編寫為向 Command 對象提供必要的參數值。
使用存儲過程的另一種可能是,我們使用一個包含從存儲過程返回的值的輸出參數。在這種情況下,我們需要更改參數的配置,以指定相應的 Direction 屬性值:
cm.Parameters.Add("@id", SqlDbType.Int)
cm.Parameters("@id").Direction = ParameterDirection.Output
如果存儲過程返回一個自動生成的數字 id 值,該參數配置就是適當的。
數據庫項目
下面要討論的最后一個主題是 Visual Studio .NET 中的數據庫項目。相對于 Visual Studio .NET 而言,這并不是真正的 ADO.NET 功能,但在使用數據庫時對此有所了解還是很有幫助的。
您可以按圖 7 所示在解決方案中添加數據庫項目。它是 Other Projects(其他項目)類別中的一個選項。
圖 7:在解決方案中添加數據庫項目
數據庫項目的優點在于它能提供一種簡便方法,將所有的數據庫腳本(例如用于創建存儲過程的腳本)直接保存在解決方案中。
通過服務器資源管理器可以直接訪問和使用數據庫,包括創建和編輯存儲過程。但是,服務器資源管理器將所有數據直接存儲在數據庫中。這種方法并不總是讓人滿意,因為我們可能需要包裝整個解決方案,并將其發送給其他開發人員,或者我們可能希望存儲過程位于源控件下。
這時,我們就可以使用數據庫項目。數據庫項目由數據庫連接和數據庫腳本組成。例如,圖 8 顯示的 ADO 解決方案添加了一個名為 PubsDb 的數據庫項目。在本示例中,我們將前面提到的 getAuthors 和 updateAuthor 存儲過程拖放到項目中。
圖 8:解決方案中的數據庫項目
將存儲過程腳本拖放到項目中后,我們可以雙擊腳本,在顯示的編輯器中處理這些腳本。所有更改都將保存回項目的腳本文件。
如果要將更改應用到數據庫本身,可以在解決方案資源管理器中右擊腳本項目,然后選擇 Run(運行)選項。這將對數據庫運行該腳本,從而應用更改。您也可以選擇 Run On(運行于)選項,此時,系統將提示您確定對哪個數據庫連接運行該腳本。
對于使用存儲過程的任何解決方案,數據庫項目都是一個很好的附加選項,因為它可以提高效率。
小結
ADO.NET 以 DataAdapter 和 DataSet 對象的方式為我們提供了一種高級、抽象的數據訪問機制。它還允許我們使用 Command 和 DataReader 對象與數據庫進行更直接的交互。第一種方法需要的代碼非常少,可以代替我們完成大量工作;而第二種方法賦予我們更多的控制能力,可以針對相應情況獲得更好的性能。通過這些選項,ADO.NET 提供了代碼的高可維護性和優良的性能,從而使之成為一種強大的高性能數據技術。
文章來源于領測軟件測試網 http://www.kjueaiud.com/