我们作者通常将软件分为两类 - 真实软件和演示软件。真实软件是在真实环境中使用的软件。演示软件用于阐释编程概念。
您在文章和书籍中看到的大部分代码都是演示软件。它必须比真实软件简单,否则读者将为那些与阐释的概念无关的细节而费神。但有时演示软件又过于极端。追求简单会忽略开发人员编写真实软件所需的细节。
最近我在数据访问方面就曾遇到这样一个问题。实际上,我见过的每个数据访问示例都使用 SQL 语句从关系数据库(例如,Microsoft SQL Server?)中读取或向其中写入。然而,在真实环境中,除了对有限的小型系统适用以外,这是很不可取的编程方法。结构合理的 n 层应用程序使用存储过程代替 SQL 语句进行数据访问。
存储过程在概念上类似于程序中的函数。它们获取输入参数,以黑盒模式运行并返回相应信息。与函数不同的是,存储过程由数据库引擎执行,而不是在程序中执行。也就是说,将信息输入到存储过程或从中输出信息都必须通过与数据库交互的技术来完成。在 Microsoft Visual Basic? 6.0 中,该技术就是传统的 ADO。在 Visual Basic .net 中,我们可以使用 ADO.NET 完成该任务。
对于许多编程任务而言,Visual Basic .NET 使得通过存储过程访问数据比使用 Visual Basic 6.0 容易得多。其中有一些用来帮助该过程的向导,一旦您学会如何避免一些错误之后,即使使用 ADO.NET 从头编写这些逻辑也并不复杂。
本文介绍了一些在 ADO.NET 中使用存储过程的基本技巧,并从只读操作开始,一直到如何使用存储过程进行数据插入、删除和更新。
您无需精通存储过程的编写也可从本文受益。许多大型编程小组的开发人员需要使用他人编写的存储过程。我们的示例之一需要将存储过程插入到示例数据库中,但我们将逐步介绍这个任务。
ADO.NET 简介
本文假设您已经了解了 ADO.NET 的基础知识。如果您在工作中从未使用过 ADO.NET 中的 DataAdapter、DataSet 和 Command 对象,则应阅读一些介绍 ADO.NET 的文章,包括 Rocky 为本专栏撰写的名为 ADO.NET 与您一文。
简而言之,DataSet 在 ADO.NET 中用作数据容器,并在与数据库断开连接时使用。DataSet 包含一个或多个 DataTable,每个 DataTable 都包含行集合。对于那些熟悉传统 ADO 环境的用户来说,DataTable 可被看作是断开连接的 Recordset。
DataAdapter 在连接到数据库时工作。单个 DataAdapter 的作用是使用数据库中的数据填充某个 DataTable,或将 DataTable 中的更改写回到数据库,或者二者兼而有之。
DataAdapter 要求 Command 对象执行各种数据库操作。Command 对象存放 SQL 语句或指定数据访问实现方法的存储过程名称。每个 DataAdapter 有四个属性,指定用于四种数据访问类型之一的命令对象。
SelectCommand:此 Command 对象用于从数据库中选择数据。
UpdateCommand:此 Command 对象用于更新数据库中的现有记录。
InsertCommand:此 Command 对象用于向数据库中插入新记录。
DeleteCommand:此 Command 对象用于删除数据库中的现有记录。
图 1 阐释了这些对象及其关系。
图 1:用于访问存储过程的主要 ADO.NET 类以及它们之间的关系
到目前为止,您所看到的演示软件示例可能将其 Command 对象配置为使用 SQL 语句进行数据访问。实际上,某些示例可能完全跳过了 Command 对象的创建,这是因为 DataAdapter 的某个构造函数允许 Command 对象选择后台创建的数据。在使用存储过程之前,让我们运行这样一个示例进行比较。
本文中的所有示例都使用 SQL Server 附带的 Northwind 示例数据库。我们还使用专门为 SQL Server 创建的 ADO.NET 类,而不是普通的 OLE DB 类。为了便于访问这些 SQL Server 类,所有示例都需要在应用程序的代码顶部加上以下代码行:
Imports System.Data.SQLClient
现在,让我们看看不使用存储过程执行数据访问的第一个示例。在此示例中,我们将在 Northwind 数据库 Products 表中检索所有产品。创建一个新 Windows 应用程序,在出现的空白 Form1 上,放置一个按钮和一个 DataGrid。将 DataGrid 的 Anchor 属性设置为全部四个边,使之随表单的扩展而扩展。在按钮的 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")
根据计算机配置的不同,可能需要更改连接字符串。建立数据库连接后,其余代码应该可以正常运行。此演示软件说明了填入和使用 DataSet 的最简单方法。
请注意,代码并不创建 Connection 对象或 Command 对象。事实上,没有这些对象,ADO.NET 便无法工作,但它们是在后台创建并使用的。实例化 SqlDataAdapter 的代码行传入 SQL 字符串(用于配置后台 Command 对象)和连接字符串(用于配置后台 Connection 对象)。
我们可以将此代码更改为使用显式 Connection 和 Command 对象,以便稍稍远离演示软件。在表单上再放置一个按钮,并将以下代码放到 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")
此代码通过显式创建 Connection 和 Command 对象,并将这些对象附加到 DataAdapter,说明了 DataAdapters 的常用性。通过在实例化 DataAdapter 时传入 cmdProducts,DataAdapter 的 SelectCommand 将自动设置。然后,可以立即使用 DataAdapter 访问数据库。
此代码的结果与前一示例中的结果相同。尽管它有点接近真实软件,但由于数据访问是通过 SQL 语句实现的,因此仍然属于演示软件。
使用简单存储过程获取数据
如何将此演示软件更改为使用存储过程?只需更改几行代码。在表单上再放置一个按钮,并将以下代码放到 Click 事件中:
Dim sConnectionString As String = _
"server=localhost;uid=sa;pwd=;database=Northwind"
Dim cnNorthwind As New SqlConnection(sConnectionString)
Dim cmdProducts As New _
SqlCommand("十件最贵的产品", cnNorthwind)
cmdProducts.CommandType = CommandType.StoredProcedure
Dim daGetProducts As New SqlDataAdapter(cmdProducts)
Dim dsProducts As New DataSet()
daGetProducts.Fill(dsProducts, "Products")
DataGrid1.DataSource = dsProducts.Tables("Products")
实例化 Command 对象时,此代码不使用 SQL 语句并替换为要使用的存储过程名称。此外,Command 对象的 CommandType 属性必须设置为 StoredProcedure。
此后的代码与上一个示例非常相似,但它返回不同的数据。存储过程查找十件最贵的产品,并只返回每个产品的名称和价格。
带输入参数的存储过程
此示例很简单,因为存储过程不需要任何输入参数。也就是说,查找十件最贵的产品不需要任何外部信息。无需外界帮助,存储过程即可完成此操作。然而,多数存储过程都需要输入参数来执行其功能。在下一个示例中,让我们看看如何向存储过程传递输入参数。我们将使用 CustomerID 来获取相关客户的所有订单,并使用名为 CustOrderHist 的存储过程(已存在于 Northwind 数据库中)。
在已使用的表单上再创建一个按钮,并将以下代码行放到按钮的 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
' 为存储过程设置参数
Dim prmCustomerID As New SqlParameter()
prmCustomerID.ParameterName = "@CustomerID"
prmCustomerID.SqlDbType = SqlDbType.VarChar
prmCustomerID.Size = 5
prmCustomerID.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")
此代码与上一个示例中的代码非常相似,不同之处在于创建 Command 对象之后,为其配置了 Parameter 对象并将此对象添加到 Command 的参数集合中。在此示例中(更接近于演示软件)将对客户 ID 进行硬编码,参数的 Value 属性通常会设置为某些用户输入数据。但是,参数的其他属性可以完全象此示例中那样设置。
此示例中的所有参数设置都是显式设置。某些开发人员喜欢这种样式,因为它便于说明。但某些开发人员喜欢使用代码行较少的等价方法:
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
cmdOrders.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")
此代码与上一示例的作用完全相同。但每个参数只需要两行代码,而不是六行。如果存储过程包含大量参数(如后面某些示例所示),所需代码行的多少就会有明显区别,因此在后面部分,我们将使用此表单。
使用存储过程更新数据库
以上示例使用存储过程从数据库中提取信息。在复杂应用程序中使用存储过程更新、插入和删除记录也很常见。让我们看看如何使用 ADO.NET 完成该操作。
在第一个示例中,我们将使用 Visual Studio? .net 中的向导编写一个存储过程集合,并创建使用这些过程的代码。尽管我们只需在此示例中编写最少量的代码,但检查向导创建的代码有助于我们理解除获取数据以外,有关与存储过程交互操作的过程。
在此示例中,我们将使用 Northwind 示例数据库中的 Customers 表。安装后的 Northwind 数据库中不包含用于更新、插入或删除客户的存储过程,但 Visual Studio .NET 中的 DataAdapter Configuration Wizard(数据适配器配置向导)可轻松地为我们编写一些存储过程。
启动新的 Windows Application(Windows 应用程序)项目。在空白的 Form1 上,放置一个 DataGrid 和两个按钮。和先前一样,更改 DataGrid 的 Anchor 属性使之锚定到全部四个边。将按钮命名为 btnFill 和 btnUpdate,并分别将其 Text 属性更改为 Fill 和 Update。
转到 Toolbox(工具箱)的 Data(数据)选项卡,将 SqlDataAdapter 控件拖动到窗体上,然后释放鼠标。这将启动 DataAdapter Configuration Wizard(数据适配器配置向导)。单击 Next(下一步)按钮开始向向导中输入信息。
首先,需要选择一个到 Northwind 数据库的连接;如果列表中未显示所需连接,则单击 New Connection(新建连接)按钮创建一个连接。然后单击 Next(下一步)按钮。
下一屏幕上将出现三种数据访问方法。其外观与图 2 类似。
图 2:选择用于 DataAdapter 的数据访问类型
此时,多数演示软件示例选择第一个选项来使用 SQL 语句。但是,我们将使用第二个选项,并让向导为我们生成一些存储过程。选择 Create new stored procedures(创建新存储过程)选项,然后单击 Next(下一步)按钮。
下一屏幕将请求 SQL 语句,指示最初从数据库中提取的数据。但并不直接使用此 SQL 语句。SQL 语句中的信息将用于构造存储过程,以便执行实际数据访问。为使示例简单起见,请输入 SQL 语句 SELECT * FROM Customers,然后按 Next(下一步)按钮。
此时,向导会请求要创建的存储过程的名称。操作共有四种 - Select、Update、Insert 和 Delete 操作。按以下方法对其命名:
Select:MSDNSelectCustomers
Update:MSDNUpdateCustomer
Insert:MSDNInsertCustomer
Delete:MSDNDeleteCustomer
选择 Yes, create them in the database for me(是的,在数据库中创建它们。)选项。此时,向导屏幕应该如图 3 所示。
图 3:命名要由 DataAdapter 向导创建的存储过程
单击 Next(下一步)按钮。向导将创建存储过程并在状态栏屏幕上指示其进度。完成后,可单击 Finish(完成)按钮退出向导。
向导创建了配置完整的 DataAdapter,但未创建 DataSet 来存放数据。这是我们下一步要做的。在 Toolbox(工具框)的 Data(数据)选项卡中,拖动 DataSet 控件。出现配置屏幕时,选择 Untyped dataset(无类型的数据集)。
现在我们准备使用 DataAdapter 填充数据集。在 btnFill 的 Click 事件中,放入以下两行代码:
SqlDataAdapter1.Fill(DataSet1, "Customers")
DataGrid1.DataSource = DataSet1.Tables("Customers")
在 btnUpdate 的 Click 事件中,放入以下代码行:
SqlDataAdapter1.Update(DataSet1, "Customers")
现在我们有了一段使用存储过程进行数据访问的有效演示软件。可以运行程序并单击 Fill 按钮获取网格中的客户列表。然后,可在窗格中编辑客户记录并选择 Update 按钮将更改放回到数据库中。
注意:编辑第一列(即 CustomerID)时将出现异常,因为在 SQL Server 中不能更新数据库记录中的主键。
查看由向导生成的代码会有所帮助,所有这些代码最初都隐藏在 Windows Form Designer generated code(Windows 窗体设计器生成的代码)区域中。单击该区域的加号可展开代码。注意以下代码,它对所需的 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()
此后的代码配置每个命令对象并为其创建参数集合。此代码与上一个示例相似,它们都使用带参数的存储过程。但向导生成的代码使用参数的某些附加属性,以使其与更改数据的存储过程协同工作。例如,用于创建 SQLInsertCommand1 的 CompanyName 参数的代码:
Me.SqlInsertCommand1.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@CompanyName", _
System.Data.SqlDbType.NVarChar, 40, "CompanyName"))
在上一个示例中,我们只为参数名称、数据类型和长度等设置了属性
此代码还会将参数的 SourceColumn 属性设置为值 CompanyName。该属性指示 DataSet 的 Customers DataTable 中与此参数对应的字段。这使 DataTable 中的值在插入操作期间自动插入到参数的 Value 属性中。让我们来详细介绍一下。
调用 SQLDataAdapter 的 Update 方法时,该方法将更新 DataSet 中的单个 DataTable。当逐行检查 DataTable 时,会查找需要更新、插入或删除的行。当找到需要插入到数据库中的行后,SQLDataAdapter 将使用由其 InsertCommand 属性设置的 Command 对象。这种情况下,Command 对象将访问 MSDNInsertCustomer 存储过程。
在该存储过程运行前,每个参数的 Value 属性都必须从插入的行中导入。配置 SQLDataAdapter1 的代码将存储过程的每个参数与 DataTable 中的相应字段相关联。这样,新 DataTable 行中的数据将自动传输到存储过程的参数。
其他存储过程参数的配置方法与此相似。但有一个不同之处值得注意。其他存储过程传入 DataTable 中数据的原始值,这些值用于检查数据是否在您不知情的情况下发生了更改。也就是说,如果您提取了某些数据,而其他人在您尝试更新前更改了该数据,您将收到并发异常。启动以上程序、提取客户,然后使用工具(例如 SQL EntERPrise Manager)更改记录中的内容,便可以看到这种情况的发生。如果您在示例程序中更改同一记录并尝试进行更新,则会收到并发异常。
从存储过程返回值
以上示例有一个不足之处。Northwind Customers 表使用数字字母形式的主键,并且必须由插入数据的应用程序生成。也就是说,如果使用以上程序插入新记录,则必须为 CustomerID 自行创建由五个字符组成的值。
在真实软件中,为新记录自动生成主键更为常见。主键通常是按顺序分配的长整数。
为新记录设置主键有两种基本技术。应用程序可调用生成下一个可用 ID 的存储过程,然后将此 ID 直接放到 DataSet 的新行中。或者,用于插入记录的存储过程可以为记录派生新 ID,然后将其作为返回值传递回应用程序。
第一种技术需要一点额外的逻辑来获取新 ID 并将其放到新记录的相应位置。使用存储过程执行插入操作与以上示例类似。
但第二种技术要求在存储过程中使用一种新型参数。到目前为止我们见到的所有参数都是默认类型,即输入参数。实际上参数分四种类型:
Input
此参数只用于将信息从应用程序传输到存储过程。
InputOutput
此参数可将信息从应用程序传输到存储过程,并将信息从存储过程传输回应用程序。
Output
此参数只用于将信息从存储过程传输回应用程序。
ReturnValue
此参数表示存储过程的返回值。SQL Server 的存储过程参数列表中不显示该参数。它只与存储过程的 RETURN 语句中的值相关联。
存储过程为主键生成新值后,通常使用存储过程中的 RETURN 语句返回该值,因此用来访问该值的参数类型是 ReturnValue 参数。
ReturnValue 参数与其他类型的参数有一个重要的区别。通常,在 ADO.NET 中为 Command 对象配置的参数的顺序并不重要。参数名称只用来与存储过程中相应的参数相匹配。但是,对于 ReturnValue 参数,它必须是列表中的第一个参数。
也就是说,为 Command 对象配置 ReturnValue 参数时,必须首先在代码中配置该参数,这样它才能获取集合中的第一个数字索引。如果先配置任何其他参数,ReturnValue 参数将不能正常工作。
为了说明带返回值的存储过程的用法,我们编写一个在 Northwind Products 表中插入记录的示例。此表被设置为使用 Identity 列自动创建新产品 ID。遗憾的是,Northwind 示例数据库不包含执行所需操作的存储过程,所以在完成示例其余部分之前,我们需要向数据库插入一个这样的存储过程。
转到 Visual Studio .net 中的 Server Explorer(服务器资源管理器)。打开 SQL Server 的节点,打开 SQL Server 实例的节点,然后打开 Northwind 数据库的节点。
右键单击 Stored Procedures(存储过程)节点,选择 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
)
AS
declare @ProductID int
SET 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 = @@IDENTITY
RETURN @ProductID
现在关闭编辑窗口,当系统询问您是否要保存更改时,单击 Yes(是)。现在存储过程就已保存到数据库中,并被命名为 MSDNInsertProduct。
现在便可以编写代码来使用此存储过程。新建 Windows 应用程序,在空白 Form1 上,放置锚定到所有四个边的 DataGrid,还需添加名为 btnFill 和 btnInsertProduct 的两个按钮。将 btnFill 的 Text 属性设置为 Fill,将 btnInsertProduct 的 Text 属性设置为 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
' 为存储过程设置参数
cmdInsertProduct.Parameters.Add(New SqlParameter("@RETURN_VALUE", SqlDbType.Int, 4, "ProductID"))
cmdInsertProduct.Parameters("@RETURN_VALUE").Direction = ParameterDirection.ReturnValue
cmdInsertProduct.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 = cmdInsertProduct
Dim dsProducts As DataSet = CType(DataGrid1.DataSource, DataSet)
Dim drNewProduct As DataRow
drNewProduct = dsProducts.Tables("Products").NewRow
drNewProduct.Item("ProductName") = "Billy's Sesame Oil"
drNewProduct.Item("SupplierID") = 4
drNewProduct.Item("CategoryID") = 7
drNewProduct.Item("QuantityPerUnit") = "6 10oz bottles"
drNewProduct.Item("UnitPrice") = 69
drNewProduct.Item("UnitsInStock") = 12
drNewProduct.Item("UnitsOnOrder") = 0
drNewProduct.Item("ReorderLevel") = 6
drNewProduct.Item("Discontinued") = False
dsProducts.Tables("Products").Rows.Add(drNewProduct)
daInsertProduct.Update(dsProducts.Tables("Products"))
MsgBox(drNewProduct.Item("ProductID"))
此代码与如上所示的代码类似,只是为返回值配置参数的代码行不同。请注意,它是第一个参数,并被设置为将返回值放回到 ProductID 字段中。
用于向数据集中插入新行的代码是标准 ADO.NET 代码,所以我们就不再赘述。它为产品记录创建一行新的适当结构(使用产品 DataTable 的 NewRow 方法),然后将数据放入行中,最后向产品 DataTable 的 Rows 集合中添加行。
现在运行程序进行测试。单击 Fill 按钮,但不对网格中的数据进行任何更改。然后按 Insert Product 按钮。将插入 Billy's Sesame Oil 的新产品记录,并且出现的消息框会通知您为其返回的 ProductID。还可以打开网格中的 Products 表,滚动到底部,并看到已添加了新行。
使用 Server Explorer(服务器资源管理器)编写参数代码
以上代码编写起来既冗长又繁琐。但是,DataAdapter Configuration Wizard(数据适配器配置向导)提示可以使用 Visual Studio 为我们编写此代码。DataAdapter Configuration Wizard(数据适配器配置向导)为完整配置所需的四个存储过程(分别是 Select、Update、Insert 和 Delete)生成了代码。假设您象以上示例一样只需要一个存储过程的代码,可以将其截短。要获得只与一个存储过程通信的预先编写好的代码,只需展开 Server Explorer(服务器资源管理器)以显示需要访问的存储过程,然后将该存储过程拖到设计界面上。将看到为该存储过程创建的 DataAdapter 和 Command 对象,代码的设计器部分包含为该存储过程配置参数所需的所有代码。可以按原样使用该代码,也可以根据需要复制并调整后使用。
小结
本文中的示例仍是演示软件,但至少足以向您说明如何访问存储过程,以便您开始编写自己的真实软件。当然,您需要了解要访问的存储过程,并且可能需要向数据库管理员 (DBA) 或其他组员咨询以获取该信息。
对于复杂系统,存储过程有许多优势。希望您在本文中学到了足够的知识,可以不必担心如何开始使用它们。第一次尝试编写代码时,您可能希望使用 DataAdapter Wizard(DataAdapter 向导)或 Server Explorer(服务器资源管理器)。但如果您能在必要时自行编写访问代码,则可以更有效地使用存储过程。