Ski*_*eak 1 vb.net sql-server output
是的,我见过这个问题。不,它没有解决我的问题。
我正在 VB.Net 中开发一个与 SQL Server 数据库接口的应用程序。目前我正在尝试让 VB.Net 应用程序在数据库上执行以下存储过程:
CREATE PROCEDURE dbo.AddSupplierAddress(
@Supplier VARCHAR(100),
@Street VARCHAR(100),
@City VARCHAR(50),
@Region VARCHAR(50),
@Code VARCHAR(7),
@Info VARCHAR(500) = NULL,
@response NVARCHAR(500) = OUTPUT
) AS
BEGIN
DECLARE @SupplierID INT, @RegionID INT
SELECT @SupplierID = supplier_id
FROM suppliers
WHERE supplier_name = @Supplier
IF @SupplierID IS NULL
BEGIN
SET @response = 'Could not add address to Supplier "' + @Supplier + '". Supplier does not exist.'
RETURN
END
SELECT @RegionID = region_id
FROM regions
WHERE region_name = @Region
IF @RegionID IS NULL
BEGIN
SET @response = 'Could not add address to Supplier "' + @Supplier + '". Region "' + @Region + '" does not exist.'
RETURN
END
IF(EXISTS(SELECT supplier_id, street FROM supplier_addresses WHERE supplier_id = @SupplierID AND street = @Street))
BEGIN
SET @response = 'Could not add address to Supplier "' + @Supplier + '". Address already exists in database.'
RETURN
END
BEGIN TRANSACTION AddSuppAddr
BEGIN TRY
INSERT supplier_addresses(supplier_id, street, city, region_id, zip_code, notes)
VALUES (@SupplierID, @Street, @City, @RegionID, @Code, @Info)
COMMIT TRANSACTION AddSuppAddr
SET @response = 'Success'
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION AddSuppAddr
DECLARE @varErrorMessage NVARCHAR(4000), @varErrorSeverity INT, @varErrorState INT;
SELECT @varErrorMessage = ERROR_MESSAGE(), @varErrorSeverity = ERROR_SEVERITY(), @varErrorState = ERROR_STATE();
RAISERROR(@varErrorMessage, @varErrorSeverity, @varErrorState);
END CATCH
END
GO
Run Code Online (Sandbox Code Playgroud)
现在我已经使用以下内容在数据库本身上运行了这个过程:
DECLARE @Resp NVARCHAR(500)
EXEC AddSupplierAddress 'Test Name', '123 main st.', 'Hamilton', 'Ontario', 'L84B5N', NULL, @Resp
PRINT @Resp
Run Code Online (Sandbox Code Playgroud)
该程序工作正常。(我遇到的一个小问题是@Resp在数据库上测试这些过程时永远不会设置为我的输出值,但这是一个不同的问题,我不想在这里解决)。在我的 VB.Net 程序中,我尝试使用以下代码运行此过程:
Private Sub CreateBtn_Click(sender As Object, e As EventArgs) Handles createBtn.Click
If CreateSupplier(supplierTxt.Text, websiteTxt.Text, True) Then
Dim message As String = ""
If setAddress Then
If AddSupplierAddress(supplierTxt.Text, streetTxt.Text, cityTxt.Text, regionTxt.Text, codeTxt.Text, infoTxt.Text, True) Then
message = "Supplier and address have been added to the database."
Else
DeleteSupplier(supplierTxt.Text)
Return
End If
Else
message = "Supplier has been added to the database."
End If
If MessageBox.Show(message & vbCrLf & "Would you like to add any Contacts?", "Data Added", MessageBoxButtons.YesNo) = DialogResult.Yes Then
Dim contact As New NewContactForm(supplierTxt.Text, False, True) With {
.MdiParent = MdiParent
}
contact.Show()
End If
End If
End Sub
Public Function AddSupplierAddress(ByVal supplier As String,
ByVal street As String,
ByVal city As String,
ByVal region As String,
ByVal code As String,
Optional info As String = "",
Optional displayError As Boolean = False) As Boolean
Dim errorMsg As String = ""
Dim CMD As New SqlCommand("AddSupplierAddress")
CMD.Parameters.Add("@Supplier", SqlDbType.VarChar).Value = supplier
CMD.Parameters.Add("@Street", SqlDbType.VarChar).Value = street
CMD.Parameters.Add("@City", SqlDbType.VarChar).Value = city
CMD.Parameters.Add("@Region", SqlDbType.VarChar).Value = region
CMD.Parameters.Add("@Code", SqlDbType.VarChar).Value = code
If Not info.Equals("") Then CMD.Parameters.Add("@Info", SqlDbType.VarChar).Value = info
If ExecuteCMDWithReturnValue(CMD, errorMsg) Then
Return True
Else
If displayError Then
MessageBox.Show(errorMsg, "Database Error")
Return False
Else
Return False
End If
End If
End Function
Public Function ExecuteCMDWithReturnValue(ByRef CMD As SqlCommand, ByRef errorMessage As String) As Boolean
Try
OpenDBConnection()
CMD.Parameters.Add("@response", SqlDbType.NVarChar, 500).Direction = ParameterDirection.Output
CMD.Connection = DB_CONNECTION
CMD.CommandType = CommandType.StoredProcedure
CMD.ExecuteNonQuery()
Dim result As String = CMD.Parameters("@response").Value
If result.Equals("Success") Then
ExecuteCMDWithReturnValue = True
Else
errorMessage = result
ExecuteCMDWithReturnValue = False
End If
Catch ex As Exception
Throw New Exception("Database Error: " & ex.Message)
ExecuteCMDWithReturnValue = False
Finally
CloseDBConnection()
End Try
End Function
Run Code Online (Sandbox Code Playgroud)
现在正如我上面所说,当我在数据库上运行存储过程时,我没有收到此错误。更奇怪的是我有另一个程序设置,它们的编码完全相同,唯一的区别是每个实例都supplier被替换了,customer并且它们都可以正常工作!
我得到的具体错误在标题中,但您不必向上滚动它:
形式参数 ""@response"" 未声明为 OUTPUT 参数,而是在请求的输出中传递的实际参数。
什么可能导致我的问题?
恭喜,您遇到了一个令人讨厌的 T-SQL 问题。它“允许”不带引号指定字符串参数默认值,以便
@response NVARCHAR(500) = OUTPUT
Run Code Online (Sandbox Code Playgroud)
实际上相当于
@response NVARCHAR(500) = 'OUTPUT'
Run Code Online (Sandbox Code Playgroud)
这当然与将参数声明为输出参数不同,因为那是
@response NVARCHAR(500) OUTPUT
Run Code Online (Sandbox Code Playgroud)
这尤其糟糕,因为默认值只允许常量——而不是函数或表达式——而引号是可选的,允许一些真正具有误导性的声明:
@from DATETIME = GETDATE
Run Code Online (Sandbox Code Playgroud)
仅当调用该过程而不指定 : 的值时,这才会失败@from:此时字符串'GETDATE'将被转换为DATETIME(当然,这将失败)。
| 归档时间: |
|
| 查看次数: |
3826 次 |
| 最近记录: |