首页 > 编程 > .NET > 正文

在 Visual Basic .NET 中使用存储过程(2)

2024-07-10 13:02:44
字体:
来源:转载
供稿:网友
从存储过程返回值
以上示例有一个不足之处。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(服务器资源管理器)。但如果您能在必要时自行编写访问代码,则可以更有效地使用存储过程。,欢迎访问网页设计爱好者web开发。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表