国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
數(shù)據(jù)訪問: 在 Visual Basic .NET 中使用存儲過程1
在 Visual Basic .NET 中使用存儲過程
發(fā)布日期: 4/1/2004 | 更新日期: 7/6/2004
Billy Hollis
摘要:Billy Hollis 講述了存儲過程對于復(fù)雜系統(tǒng)的益處,將存儲過程提到了超出演示軟件的高度,并提供了一些手頭的示例,以說明如何訪問存儲過程以及如何開始在應(yīng)用程序中使用這些存儲過程。
下載StoredProcVB.NET.exe
我們這些作者傾向于將軟件分為兩類:實際軟件 和演示軟件。 實際軟件就是那些在現(xiàn)實中能夠真正運作的軟件。 演示軟件則是為了說明某些編程概念而編寫的軟件。
各種文章和書籍上所見到的大多數(shù)代碼都是演示軟件。 這些軟件必須比實際軟件來得簡單;否則,讀者將陷入與所說明概念毫無關(guān)系的各種細(xì)節(jié)中。 但有時演示軟件簡單得過了火。 一味追求簡單就可能忽略在編寫實際軟件時所必需的一些細(xì)節(jié)。
我最近注意到的這種例子是關(guān)于數(shù)據(jù)訪問的。 我所看到的每個數(shù)據(jù)訪問示例基本上都使用 SQL 語句對關(guān)系數(shù)據(jù)庫進(jìn)行讀寫訪問,這樣的關(guān)系數(shù)據(jù)庫如 Microsoft SQL Server?。 然而,在現(xiàn)實中,這種做法被認(rèn)為是一種錯誤的編程習(xí)慣,可能一些小型的、有限的系統(tǒng)除外。 一個恰當(dāng)構(gòu)造的 n 層應(yīng)用程序使用存儲過程進(jìn)行數(shù)據(jù)訪問,而不是使用 SQL 語句。
在概念上,存儲過程類似于程序中的函數(shù)。 存儲過程獲得輸入?yún)?shù),以黑盒子 形式運行,并返回適當(dāng)?shù)男畔ⅰ?與函數(shù)的不同之處在于,存儲過程由數(shù)據(jù)庫引擎執(zhí)行,而不是在程序內(nèi)部執(zhí)行的。 這意味著必須利用一種能夠與數(shù)據(jù)庫接口的技術(shù)從存儲過程獲取信息或向其中輸入信息。 在 Microsoft Visual Basic? 6.0 中,這個技術(shù)就是傳統(tǒng)的 ADO。 在 Visual Basic .NET 中,我們則可以通過 ADO.NET 完成。
如同對很多編程任務(wù)一樣,Visual Basic .NET 使得利用存儲過程訪問數(shù)據(jù)的操作比 Visual Basic 6.0 利用存儲過程進(jìn)行數(shù)據(jù)訪問容易得多。 Visual Basic .NET 提供了一些向?qū)б詭椭瓿纱诉^程,只要您知道如何避免一些太隨意的語句,即便是利用 ADO.NET 從頭開始編寫這種邏輯也不是過分復(fù)雜的事情。
本文包括一些在利用 ADO.NET 對存儲過程進(jìn)行操作時的基本方法,首先介紹了一種只讀操作,然后繼續(xù)講述使用存儲過程進(jìn)行插入、刪除和更新數(shù)據(jù)。
即便您不能熟練地編寫存儲過程,您也將從本文中獲益匪淺。 大型編程團隊中的很多開發(fā)人員都需要能夠使用由別人編寫的存儲過程。 我們的示例之一就是需要將一個存儲過程插入到示例數(shù)據(jù)庫中,但我們將循序漸進(jìn)地講述該項任務(wù)。
簡要回顧 ADO.NET
對本文而言,我必須假設(shè)您已經(jīng)具備了有關(guān) ADO.NET 的基礎(chǔ)知識。如果您尚未使用 ADO.NET 中的 DataAdapters、DataSets 和 Command 對象完成一些任務(wù),那么您應(yīng)該讀讀有關(guān) ADO.NET 的入門文章,包括 Rocky 為本專欄撰寫的一篇文章,名為ADO.NET and You
簡要回顧一下,DataSets 在 ADO.NET 中用作數(shù)據(jù)容器,在從數(shù)據(jù)庫斷開時使用。 DataSet 包含一個或多個 DataTables,其中每個包含一個行集。 對于熟悉傳統(tǒng)的 ADO 的開發(fā)人員而言,DataTable大致可看作是一個斷開的記錄集。
DataAdapters 在連接到數(shù)據(jù)庫時起作用。 一個 DataAdapter 的任務(wù)或者是利用來自數(shù)據(jù)庫的數(shù)據(jù)填充其中一個 DataTables,或者是將 DataTable 中的更改寫回數(shù)據(jù)庫中,或者是這二者都進(jìn)行。
DataAdapters 需要 Command 對象來執(zhí)行各種數(shù)據(jù)庫操作。 Command 對象中或者包含一條 SQL 語句,或者包含一個存儲過程名稱,用以指定要如何完成數(shù)據(jù)訪問。 每個 DataAdapter都有四個屬性,表明用于四種數(shù)據(jù)訪問類型中每一種類型的命令對象:
SelectCommand:此 Command 對象用于從數(shù)據(jù)庫中選擇數(shù)據(jù)。
UpdateCommand:此 Command 對象用于更新數(shù)據(jù)庫中現(xiàn)有的記錄。
InsertCommand: 此 Command 對象用于向數(shù)據(jù)庫中插入新記錄。
DeleteCommand:此 Command 對象用于刪除數(shù)據(jù)庫中現(xiàn)有的記錄。
我們可以用圖的形式來表示這些對象及其關(guān)系,如圖 1 所示。
圖 1. 用于訪問存儲過程的主要 ADO.NET 類,及其相互關(guān)系
到目前為止,您所看到的演示軟件示例可能都是將其 Command 對象配置為利用 SQL 語句進(jìn)行數(shù)據(jù)訪問。 實際上,其中的某些示例很可能還完全繞過了 Command 對象的創(chuàng)建,因為 DataAdapter的其中一個構(gòu)造函數(shù)允許在后臺創(chuàng)建用于選擇數(shù)據(jù)的 Command 對象。 在開始使用存儲過程之前,讓我們演示這樣一個示例以作為比較。
本文中所有示例都使用 SQL Server 所附帶的 Northwind 示例數(shù)據(jù)庫。 我們還將使用專門針對 SQL Server 而創(chuàng)建的 ADO.NET 類,而不是使用通用的 OLE DB 類。 為了便于訪問這些 SQL Server 類,所有示例都需要在應(yīng)用程序的代碼最上面包括以下一行:
Imports System.Data.SQLClient
現(xiàn)在,開始我們的第一個示例,即不通過存儲過程執(zhí)行數(shù)據(jù)訪問。 在此示例中,我們將檢索 Northwind 數(shù)據(jù)庫 Products 表中所有的產(chǎn)品。 創(chuàng)建一個新的 Windows 應(yīng)用程序,并在所顯示的空白 Form1 上放置一個按鈕和一個 DataGrid。 將 DataGrid的 Anchor 屬性設(shè)置到全部四條邊,這樣一來,它就會隨著窗體的擴展而擴展。 在按鈕的 Click 事件中,加入以下代碼:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim sSQL As String = "SELECT * FROM Products"Dim daGetProducts As New SqlDataAdapter(sSQL, sConnectionString)Dim dsProducts As New DataSet()daGetProducts.Fill(dsProducts, "Products")DataGrid1.DataSource = dsProducts.Tables("Products")
根據(jù)計算機的具體配置,您可能需要更改連接字符串。 然而,只要建立了數(shù)據(jù)庫連接,代碼的其他部分就應(yīng)該運行正常。 此演示軟件顯示了用于填充和使用 DataSet 的最簡單且可行的方法。
請注意,該代碼并沒有創(chuàng)建 Connection 對象或 Command 對象。 在現(xiàn)實中,如果沒有這些對象,ADO.NET 是不能運行的,但這些對象是在后臺創(chuàng)建并使用的。 用于實例化 SqlDataAdapter 的代碼行傳遞進(jìn)來一個 SQL 字符串(以配置這個后臺 Command 對象)和一個連接字符串(以配置這個后臺 Connection 對象)。
我們可以更改此代碼以使用顯式的 Connection 和 Command 對象,這樣離演示軟件稍微遠(yuǎn)了一些。 在窗體上放置另一個按鈕,并將以下代碼加入該按鈕的 Click 事件中:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim sSQL As String = "SELECT * FROM Products"Dim cnNorthwind As New SqlConnection(sConnectionString)Dim cmdProducts As New SqlCommand(sSQL, cnNorthwind)Dim daGetProducts As New SqlDataAdapter(cmdProducts)Dim dsProducts As New DataSet()daGetProducts.Fill(dsProducts, "Products")DataGrid1.DataSource = dsProducts.Tables("Products")
此代碼顯示了 DataAdapters 的更常見的使用方法;即通過顯式創(chuàng)建 Connection 和 Command 對象并將這些對象附加到 DataAdapter。 通過在實例化 DataAdapter 時傳遞到 cmdProducts 中,DataAdapter 的 SelectCommand 得以自動設(shè)置。 隨后,DataAdapter 馬上就可用于訪問數(shù)據(jù)庫。
此代碼的結(jié)果與前一示例的結(jié)果完全相同。 但這段代碼較接近于真實軟件,它的更多方面還是像演示軟件,因為數(shù)據(jù)訪問是通過 SQL 語句完成的。
利用簡單的存儲過程獲取數(shù)據(jù)
如何更改此演示軟件以使用存儲過程呢? 只需更改其中的兩行。 在窗體上放置另一個按鈕,并將以下代碼加入該按鈕的 Click 事件中:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim cnNorthwind As New SqlConnection(sConnectionString)Dim cmdProducts As New _SqlCommand("Ten Most Expensive Products", cnNorthwind)cmdProducts.CommandType = CommandType.StoredProcedureDim daGetProducts As New SqlDataAdapter(cmdProducts)Dim dsProducts As New DataSet()daGetProducts.Fill(dsProducts, "Products")DataGrid1.DataSource = dsProducts.Tables("Products")
這段代碼不再使用 SQL 語句,取而代之的是在實例化 Command 對象時將使用存儲過程名稱。 此外,該 Command對象的 CommandType 屬性必須設(shè)置為 StoredProcedure。
從該行以后,代碼與前一示例完全相同,但返回不同的數(shù)據(jù)。 該存儲過程會找出十項最貴的產(chǎn)品,且僅返回每項產(chǎn)品的名稱和價格。
帶輸入?yún)?shù)的存儲過程
此示例相當(dāng)簡單,因為其存儲過程不需要任何輸入?yún)?shù)。 也就是說,找出十項最貴產(chǎn)品的操作并不需要任何外部信息。 該存儲過程不需要任何外部幫助即可完成操作。 然而,大多數(shù)存儲過程卻的確需要輸入?yún)?shù)以執(zhí)行其功能。 作為下一個示例,讓我們看看如何向存儲過程傳遞輸入?yún)?shù)。 我們將利用 Northwind 數(shù)據(jù)庫中已有的一個名為 CustOrderHist 的存儲過程,并使用 CustomerID 獲取相關(guān)客戶的所有訂單。
在我們一直使用的窗體上創(chuàng)建另一個按鈕,并在該按鈕的 Click 事件中加入以下代碼:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim cnNorthwind As New SqlConnection(sConnectionString)Dim cmdOrders As New SqlCommand("CustOrderHist", cnNorthwind)cmdOrders.CommandType = CommandType.StoredProcedure' Set up parameter for stored procedureDim prmCustomerID As New SqlParameter()prmCustomerID.ParameterName = "@CustomerID"prmCustomerID.SqlDbType = SqlDbType.VarCharprmCustomerID.Size = 5prmCustomerID.Value = "ALFKI"cmdOrders.Parameters.Add(prmCustomerID)Dim daGetOrders As New SqlDataAdapter(cmdOrders)Dim dsOrders As New DataSet()daGetOrders.Fill(dsOrders, "Orders")DataGrid1.DataSource = dsOrders.Tables("Orders")
這段代碼看起來很像前一示例中的代碼,不同之處在于,在創(chuàng)建 Command 對象之后,為該對象配置了一個 Parameter對象并將其添加到了該命令的參數(shù)集合中。 在此示例中,我們硬編碼了一個客戶 ID(更接近于演示軟件),而且在通常情況下參數(shù)的 Value屬性應(yīng)該被設(shè)置成某些用戶輸入數(shù)據(jù)。 然而,可完全按此示例中所示的方式設(shè)定該參數(shù)的其他屬性。
此示例顯式地設(shè)置了所有參數(shù)。 有些開發(fā)人員喜歡這種風(fēng)格,且這種風(fēng)格適用于指導(dǎo)目的。 然而,有些開發(fā)人員更喜歡另一種等效的形式,這種形式的代碼行更少:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim cnNorthwind As New SqlConnection(sConnectionString)Dim cmdOrders As New SqlCommand("CustOrderHist", cnNorthwind)cmdOrders.CommandType = CommandType.StoredProcedurecmdOrders.Parameters.Add(New _SqlParameter("@CustomerID", SqlDbType.VarChar, 5))cmdOrders.Parameters("@CustomerID").Value = "ALFKI"Dim daGetOrders As New SqlDataAdapter(cmdOrders)Dim dsOrders As New DataSet()daGetOrders.Fill(dsOrders, "Orders")DataGrid1.DataSource = dsOrders.Tables("Orders")
這段代碼的功能與前一示例的功能完全相同。 然而,對每個參數(shù),它只需兩行代碼,而不是六行。 如果一個存儲過程具有很多參數(shù)(稍后的一些示例就會有很多參數(shù)),這樣一來所需的代碼行數(shù)可能會產(chǎn)生很大的區(qū)別,所以從此往后,我們將使用這種形式。
使用存儲過程更新數(shù)據(jù)庫
以上的幾個示例使用了存儲過程從數(shù)據(jù)庫中獲取信息。 在一些復(fù)雜的應(yīng)用程序中,也經(jīng)常使用存儲過程來更新、插入和刪除記錄。 讓我們看看如何利用 ADO.NET 進(jìn)行這些操作。
作為第一個示例,我們將允許 Visual Studio? .NET 中的向?qū)槲覀兙帉懸唤M存儲過程,并創(chuàng)建相應(yīng)代碼以使用這些過程。 盡管我們只需為此示例編寫最少量的代碼,但是仔細(xì)查看向?qū)鶆?chuàng)建的代碼能夠幫助我們理解與存儲過程接口的過程,以便除獲取數(shù)據(jù)之外還可以進(jìn)行其他操作。
對于本示例,我們將使用 Northwind 示例數(shù)據(jù)庫中的 Customers 表。 在安裝 Northwind 數(shù)據(jù)庫時,其中并不包含用于更新、插入或刪除客戶的存儲過程,但 Visual Studio .NET 中的 DataAdapter 配置向?qū)Э珊芊奖愕鼐帉懸恍┐鎯^程。
開始一個新的 Windows Application 項目。 在空白的 Form1 上,放置一個 DataGrid和兩個按鈕。 跟前面一樣,將 DataGrid 的 Anchor 屬性更改為定位到所有四條邊。 將按鈕命名為 btnFill 和 btnUpdate,并將其 Text 屬性分別更改為 Fill 和 Update。
轉(zhuǎn)至 Toolbox 的 Data 選項卡,將一個 SqlDataAdapter 控件拖到窗體上然后釋放。 這樣將打開一個 DataAdapter 配置向?qū)А?單擊 Next 按鈕,開始在向?qū)е休斎胄畔ⅰ?div style="height:15px;">
首先,需要選擇一個到 Northwind 數(shù)據(jù)庫的連接,或者,如果列表中沒有可用連接,則單擊 New Connection按鈕,創(chuàng)建一個連接。 然后單擊 Next 按鈕。
下一個屏幕中包含用于訪問數(shù)據(jù)的三種可選途徑。 該屏幕如圖 2 所示。
圖 2. 為 DataAdapter 選擇數(shù)據(jù)訪問類型
在此處,大多數(shù)演示軟件示例會使用第一個選項以使用 SQL 語句。 然而,我們將改用第二個選項,并讓向?qū)槲覀儎?chuàng)建一些存儲過程。 選擇 Create new stored procedures 選項,然后單擊 Next 按鈕。
下一個屏幕需要一條 SQL 語句以指明初始時從數(shù)據(jù)庫中獲取的數(shù)據(jù)。 然而,并不會直接使用此 SQL 語句。 此 SQL 語句中的信息將用于構(gòu)建進(jìn)行實際數(shù)據(jù)訪問的存儲過程。 為了使此示例保持簡單明了,請輸入 SQL 語句 SELECT * FROM Customers,然后按 Next 按鈕。
在此處,向?qū)б筇峁⒁獎?chuàng)建的存儲過程的名稱。 有四個存儲過程 — 選擇、更新、插入和刪除操作。 按以下方式命名:
選擇:MSDNSelectCustomers
更新:MSDNUpdateCustomer
插入:MSDNInsertCustomer
刪除:MSDNDeleteCustomer
保持選中 Yes, create them in the database for me 選項。 此時,向?qū)聊粦?yīng)該類似圖 3 所示。
圖 3. 為 DataAdapter 向?qū)⒁獎?chuàng)建的存儲過程命名
單擊 Next 按鈕。 向?qū)?chuàng)建這些存儲過程,并在狀態(tài)屏幕上顯示其進(jìn)度。 完成后,您可以單擊 Finish按鈕,退出向?qū)А?div style="height:15px;">
該向?qū)?chuàng)建了一個完全配置好的 DataAdapter,但并未創(chuàng)建 DataSet 來容納數(shù)據(jù)。 下一步,我們將進(jìn)行該操作。 從 Toolbox 的 Data 選項卡中,拖過一個 DataSet 控件。 當(dāng)顯示其配置屏幕時,選擇 Untyped dataset。
現(xiàn)在,就可利用該 DataAdapter 填充該數(shù)據(jù)集了。 在 btnFill 的 Click事件中,加入以下兩行代碼:
SqlDataAdapter1.Fill(DataSet1, "Customers")DataGrid1.DataSource = DataSet1.Tables("Customers")
在 btnUpdate 的 Click 事件中,加入以下一行:
SqlDataAdapter1.Update(DataSet1, "Customers")
現(xiàn)在,我們就擁有了一個可正常工作的演示軟件,它使用存儲過程進(jìn)行數(shù)據(jù)訪問。 您可以運行該程序,并單擊 Fill 按鈕以獲取網(wǎng)格中的用戶列表。 然后,您可以在網(wǎng)格中編輯用戶數(shù)據(jù),并選擇 Update 按鈕將這些更改返回到數(shù)據(jù)庫中。
注如果編輯第一列,也就是 CustomerID,將發(fā)生異常,因為您不能在 SQL Server 中更新一條數(shù)據(jù)庫記錄中的主鍵。
查看一下向?qū)傻拇a還是很有指導(dǎo)意義的,所有這些代碼最初都隱藏在 Windows Form Designer generated code 區(qū)域中。 單擊該區(qū)域相應(yīng)的加號,展開該代碼。 注意以下代碼,這些代碼會實例化 SQLDataAdapter及其所需的四個命令對象:
Me.SqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter()Me.SqlSelectCommand1 = New System.Data.SqlClient.SqlCommand()Me.SqlInsertCommand1 = New System.Data.SqlClient.SqlCommand()Me.SqlUpdateCommand1 = New System.Data.SqlClient.SqlCommand()Me.SqlDeleteCommand1 = New System.Data.SqlClient.SqlCommand()
再往下,您將看到用于配置每個命令對象并為其創(chuàng)建參數(shù)集合的代碼。 這段代碼類似于前面的使用帶參數(shù)的存儲過程的示例中的代碼。 然而,向?qū)傻拇a使用了附加的一些參數(shù)屬性,以允許這些參數(shù)屬性與更改數(shù)據(jù)的各種存儲過程一起使用。 例如,用于為 SQLInsertCommand1 創(chuàng)建 CompanyName 參數(shù)的代碼:
Me.SqlInsertCommand1.Parameters.Add(New _System.Data.SqlClient.SqlParameter("@CompanyName", _System.Data.SqlDbType.NVarChar, 40, "CompanyName"))
在前面的示例中,我們僅為參數(shù)名稱、數(shù)據(jù)類型和長度設(shè)置了屬性。 這段代碼還將該參數(shù)的 SourceColumn 屬性設(shè)置為 CompanyName 值。 該屬性表明了該數(shù)據(jù)集的 CustomersDataTable 中與此參數(shù)對應(yīng)的字段。 這就允許在插入操作中將 DataTable 中的值自動插入該參數(shù)的 Value 屬性中。 讓我們更詳細(xì)地討論一下這一點。
當(dāng) SQLDataAdapter 的 Update 方法被調(diào)用時,它會更新 DataSet 中的單個 DataTable。 對 DataTable 逐行進(jìn)行檢查,查找需要更新、插入或刪除的行。 當(dāng)發(fā)現(xiàn)要將新的一行插入數(shù)據(jù)庫時,SQLDataAdapter 會使用其 InsertCommand 屬性所設(shè)定的 Command 對象。 在這里,該 Command 對象訪問了 MSDNInsertCustomer 存儲過程。
在能運行該存儲過程之前,必須從正被插入的行填充每個參數(shù)的 Value 屬性。 用于配置 SQLDataAdapter1的代碼將該存儲過程的每個參數(shù)與 DataTable 中的相應(yīng)字段關(guān)聯(lián)起來。 這就允許將新的 DataTable 行的數(shù)據(jù)自動傳送到該存儲過程的參數(shù)。
其他存儲過程的參數(shù)可類似地進(jìn)行配置。 有一個不同之處值得注意。 其他存儲過程會傳入 DataTable中數(shù)據(jù)的初始值,這些值用于檢查數(shù)據(jù)在您不知情的情況下未發(fā)生更改。 也就是說,如果您獲取了某些數(shù)據(jù),而在您嘗試更新之前別人已經(jīng)進(jìn)行了更改,您則會得到一個并發(fā)異常。 啟動上述程序,獲取客戶信息,然后使用某個工具(如 SQL Enterprise Manager)更改記錄中的某項內(nèi)容,您就可以看到這種情況發(fā)生。 如果您在示例程序中更改同一條記錄并試圖更新,則會得到一個并發(fā)異常。
從存儲過程返回值
以上示例在一個方面存在著不足。 Northwind Customers 表使用了字母數(shù)字主鍵,且應(yīng)用程序在插入數(shù)據(jù)時必須組成這些主鍵。 也就是說,如果您利用以上的程序插入一條新記錄,則必須自己為 CustomerID 創(chuàng)建一個 5 個字符的值。
在實際軟件中,更常見的做法是為新記錄自動生成主鍵。 這種主鍵通常是一個按順序分配的長整數(shù)。
有兩種基本方法可用于為新記錄設(shè)置主鍵。 應(yīng)用程序可以調(diào)用一個存儲過程以生成下一個可用的 ID,然后該應(yīng)用程序可以將該 ID 直接放入 DataSet 的新行中。 或者,用于插入記錄的存儲過程可以為該記錄派生新的 ID,然后作為一個返回值將其傳遞回該應(yīng)用程序中。
第一種方法需要一些額外的邏輯以獲取新 ID 并將其放到新記錄中的合適位置處。 使用存儲過程進(jìn)行插入操作與以上的示例類似。
然而,第二種方法需要一種新的參數(shù)用于存儲過程。 到目前為止,我們所見到的所有參數(shù)都是默認(rèn)類型,也就是一個輸入?yún)?shù)。 實際上,有四種類型的參數(shù):
Input
這種參數(shù)僅用于將信息從應(yīng)用程序傳遞到存儲過程。
InputOutput
這種參數(shù)可以將信息傳入存儲過程,也可將信息從存儲過程傳遞回應(yīng)用程序。
Output
這種參數(shù)只將信息從存儲過程傳遞回應(yīng)用程序。
ReturnValue
這種參數(shù)代表從存儲過程返回的值。 這種參數(shù)并不出現(xiàn)在 SQL Server 中用于存儲過程的參數(shù)列表中。 它只與存儲過程的 RETURN 語句中的某個值相關(guān)。
當(dāng)存儲過程為主鍵生成一個新值時,常用的做法是利用該存儲過程中的一條 RETURN 語句返回該值,因此,用于訪問該值的參數(shù)類型是 ReturnValue 參數(shù)。
ReturnValue 參數(shù)與其他類型的參數(shù)之間有一個重要的不同之處。 在通常情況下,在 ADO.NET 中為 Command對象配置各個參數(shù)的順序無關(guān)緊要。 各個參數(shù)的名稱可用于將其與存儲過程中的相應(yīng)參數(shù)進(jìn)行匹配。 然而,對于 ReturnValue參數(shù)而言,它必須 是該列表中的第一個參數(shù)。
這就意味著,當(dāng)您為一個 Command 對象配置 ReturnValue參數(shù)時,必須在代碼中首先配置這個參數(shù),這樣它就可以獲取集合中的第一個數(shù)字索引。 如果您首先配置任何其他的參數(shù),ReturnValue參數(shù)將不會正常運行。
為了演示帶返回值的存儲過程的使用,我們將執(zhí)行一個示例 — 將一條記錄插入 Northwind Products 表。 這個表被設(shè)置為利用一個 Identity 列自動生成新的產(chǎn)品 ID。 不巧的是,Northwind 示例數(shù)據(jù)庫中并不包含一個可完成我們想要的操作的存儲過程,因此,在進(jìn)行本示例的剩余部分之前,我們必須在數(shù)據(jù)庫中插入相應(yīng)的存儲過程。
轉(zhuǎn)至 Visual Studio .NET 中的 Server Explorer。 打開 SQL Server 節(jié)點,然后打開相應(yīng) SQL Server 實例的節(jié)點。 然后打開 Northwind 數(shù)據(jù)庫節(jié)點。
右鍵單擊 Stored Procedures 節(jié)點,然后選擇 New Stored Procedure。 在所顯示的編輯窗口中,用以下文本替換其中所有的文本:
ALTER PROCEDURE dbo.MSDNInsertProduct(@ProductName nvarchar(40),@SupplierID int,@CategoryID int,@QuantityPerUnit nvarchar(20),@UnitPrice money,@UnitsInStock smallint,@UnitsOnOrder smallint,@ReorderLevel smallint,@Discontinued bit)ASdeclare @ProductID intSET NOCOUNT OFF;INSERT INTO Products(ProductName, SupplierID, CategoryID, QuantityPerUnit,UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued) VALUES(@ProductName, @SupplierID, @CategoryID, @QuantityPerUnit, @UnitPrice,@UnitsInStock, @UnitsOnOrder, @ReorderLevel, @Discontinued);SELECT @ProductID = @@IDENTITYRETURN @ProductID
現(xiàn)在,關(guān)閉編輯窗口,將詢問您是否想要保存更改,單擊 Yes。 該存儲過程已被保存在數(shù)據(jù)庫中,且將被命名為 MSDNInsertProduct。
現(xiàn)在,我們就可以編寫代碼來使用該存儲過程了。 創(chuàng)建一個新的 Windows 應(yīng)用程序,在空白 Form1 上,放置一個 DataGrid,并將其定位到所有四條邊。 另外,添加名為 btnFill 和 btnInsertProduct的兩個按鈕。 將 btnFill 的 Text 屬性設(shè)置為 Fill 而將 btnInsertProduct 的 Text 屬性設(shè)置為 Insert Product。
在 btnFill 的 click 事件中,放入以下代碼:
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim sSQL As String = "SELECT * FROM Products"Dim daGetProducts As New SqlDataAdapter(sSQL, sConnectionString)Dim dsProducts As New DataSet()daGetProducts.Fill(dsProducts, "Products")DataGrid1.DataSource = dsProducts
這段代碼與本文中前面所見的代碼幾乎完全相同,因此我們不再討論。 如有必要,不要忘記更改連接字符串,并將 SQLClient 命名空間的 Imports 語句放在該項目代碼的開始位置處。 然后將以下代碼放到 btnInsertProduct 的 Click事件中。
Dim sConnectionString As String = _"server=localhost;uid=sa;pwd=;database=Northwind"Dim cnNorthwind As New SqlConnection(sConnectionString)Dim cmdInsertProduct As New SqlCommand("MSDNInsertProduct", cnNorthwind)cmdInsertProduct.CommandType = CommandType.StoredProcedure' Set up parameters for stored procedurecmdInsertProduct.Parameters.Add(New SqlParameter("@RETURN_VALUE", SqlDbType.Int, 4, "ProductID"))cmdInsertProduct.Parameters("@RETURN_VALUE").Direction = ParameterDirection.ReturnValuecmdInsertProduct.Parameters.Add(New SqlParameter("@ProductName", _SqlDbType.NVarChar, 40, "ProductName"))cmdInsertProduct.Parameters.Add(New SqlParameter("@SupplierID", _SqlDbType.Int, 4, "SupplierID"))cmdInsertProduct.Parameters.Add(New SqlParameter("@CategoryID", _SqlDbType.Int, 4, "CategoryID"))cmdInsertProduct.Parameters.Add(New SqlParameter("@QuantityPerUnit", _SqlDbType.NVarChar, 20, "QuantityPerUnit"))cmdInsertProduct.Parameters.Add(New SqlParameter("@UnitPrice", _SqlDbType.Money, 8, "UnitPrice"))cmdInsertProduct.Parameters.Add(New SqlParameter("@UnitsInStock", _SqlDbType.SmallInt, 2, "UnitsInStock"))cmdInsertProduct.Parameters.Add(New SqlParameter("@UnitsOnOrder", _SqlDbType.SmallInt, 2, "UnitsOnOrder"))cmdInsertProduct.Parameters.Add(New SqlParameter("@ReorderLevel", _SqlDbType.SmallInt, 2, "ReorderLevel"))cmdInsertProduct.Parameters.Add(New SqlParameter("@Discontinued", _SqlDbType.Bit, 1, "Discontinued"))Dim daInsertProduct As New SqlDataAdapter()daInsertProduct.InsertCommand = cmdInsertProductDim dsProducts As DataSet = CType(DataGrid1.DataSource, DataSet)Dim drNewProduct As DataRowdrNewProduct = dsProducts.Tables("Products").NewRowdrNewProduct.Item("ProductName") = "Billy's Sesame Oil"drNewProduct.Item("SupplierID") = 4drNewProduct.Item("CategoryID") = 7drNewProduct.Item("QuantityPerUnit") = "6 10oz bottles"drNewProduct.Item("UnitPrice") = 69drNewProduct.Item("UnitsInStock") = 12drNewProduct.Item("UnitsOnOrder") = 0drNewProduct.Item("ReorderLevel") = 6drNewProduct.Item("Discontinued") = FalsedsProducts.Tables("Products").Rows.Add(drNewProduct)daInsertProduct.Update(dsProducts.Tables("Products"))MsgBox(drNewProduct.Item("ProductID"))
除了用于為返回值配置參數(shù)的各行外,這段代碼與我們前面所見的代碼很相似。 請注意,這是第一個參數(shù),設(shè)置此參數(shù)是為了將返回值放回到 ProductID 字段。
用于將新行插入數(shù)據(jù)集的代碼是標(biāo)準(zhǔn)的 ADO.NET 代碼,因此我們將不再詳述。 它為產(chǎn)品記錄創(chuàng)建一個具有合適結(jié)構(gòu)的新行(利用 products DataTable 的 NewRow 方法),將數(shù)據(jù)放入行中,最后將該行加入 products DataTable 的 Rows 集合中。
現(xiàn)在,運行該程序以進(jìn)行測試。 單擊 Fill 按鈕,但是不對網(wǎng)格中的任何數(shù)據(jù)進(jìn)行更改。 然后按 Insert Product按鈕。 將插入一條對應(yīng)于 Billy's Sesame Oil 的新產(chǎn)品記錄,且一個消息框?qū)@示針對該記錄返回的 ProductID。 您也可以在網(wǎng)格中打開 Products 表,滾動瀏覽到底部,即可注意到已添加的新記錄。
使用 Server Explorer 編寫參數(shù)代碼
以上的代碼編寫起來乏味而重復(fù)。 然而,DataAdapter 配置向?qū)崾緦嶋H上 Visual Studio 可以替我們編寫這些代碼。 DataAdapter 配置向?qū)橐粋€完整配置中的所有四個存儲過程(Select、Update、Insert 和 Delete 各一個)生成代碼。 假設(shè)您正需要如上例所示的某一個存儲過程的代碼,那該如何呢? 您仍然可以走一條捷徑。 要獲得只是與一個存儲過程接口的預(yù)編寫代碼,只需展開 Server Explorer 以顯示您想要使用的存儲過程,然后將該存儲過程拖到設(shè)計界面上即可。 您將看到只是為該存儲過程創(chuàng)建的 DataAdapter 和 Command對象,且該代碼的設(shè)計器部分將包含為該存儲過程配置各個參數(shù)所需的全部代碼。 您可原封不動地使用該代碼,也可根據(jù)自己的需要而復(fù)制并改寫該代碼。
小結(jié)
本文中的各個示例仍然是演示軟件,但是至少這些示例向您展示的使用存儲過程的相關(guān)信息足以使您開始編寫自己的軟件。 當(dāng)然了,您需要理解您將要使用的存儲過程,并且可能需要詢問數(shù)據(jù)庫管理員 (DBA) 或其他小組成員以獲得這些信息。
對于復(fù)雜系統(tǒng)而言,存儲過程具有很多優(yōu)點。 我希望您已從本文中學(xué)習(xí)到足夠的知識,而不會對開始使用存儲過程而心存畏懼。 在最初的一些嘗試中,您可能想要使用 DataAdapter 向?qū)Щ蛘?Server Explorer 為您編寫大多數(shù)代碼,但如果您能夠在需要的時候編寫自己的訪問代碼,那么您工作起來將事半功倍。
轉(zhuǎn)到原英文頁面
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
存儲過程和自定義函數(shù)
簡單防sql注入攻擊數(shù)據(jù)庫處理代碼示例
C#中使用Oracle存儲過程返回結(jié)果集
Oracle官方示例---Java 存儲過程示例代碼區(qū)
使用 IBM Data Studio 開發(fā)調(diào)試 DB2 存儲過程
御麗詩妃談mysql
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服