Формальный параметр "@response" "не был объявлен как параметр OUTPUT, но фактический параметр передан в запрошенном выводе - PullRequest
0 голосов
/ 09 ноября 2018

Да, я видел этот вопрос. Нет, это не решило моих проблем.

Я работаю над приложением в 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

Теперь я выполнил эту процедуру для самой базы данных, используя следующее:

DECLARE @Resp NVARCHAR(500)
EXEC AddSupplierAddress 'Test Name', '123 main st.', 'Hamilton', 'Ontario', 'L84B5N', NULL, @Resp
PRINT @Resp

Процедура работает отлично. (У меня небольшая проблема в том, что @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

Теперь, как я уже говорил выше, я не получаю эту ошибку при запуске хранимой процедуры в базе данных. Что еще более странно, так это то, что у меня есть другая настройка процедур, которые закодированы точно так же, с той лишь разницей, что каждый экземпляр supplier заменен на customer, и все они работают нормально!

Конкретная ошибка, которую я получаю, находится в заголовке, но вам не нужно ее прокручивать:

Формальный параметр "@response" "не был объявлен как параметр OUTPUT, но фактический параметр передан в запрошенном выводе.

Что может быть причиной моей проблемы?

1 Ответ

0 голосов
/ 09 ноября 2018

Поздравляю, вы столкнулись с неприятной ошибкой T-SQL. Он «позволяет» указывать параметры строки по умолчанию без кавычек, так что

@response NVARCHAR(500) = OUTPUT

Фактически эквивалентно

@response NVARCHAR(500) = 'OUTPUT'

Это, конечно, не то же самое, что объявление параметра в качестве выходного параметра, поскольку это

@response NVARCHAR(500) OUTPUT

Это особенно плохо, потому что значения по умолчанию допускают только константы - не функции или выражения - и все же необязательные кавычки допускают некоторые действительно вводящие в заблуждение объявления:

@from DATETIME = GETDATE

Это не удастся, только когда процедура вызывается без указания значения для @from: в этот момент строка 'GETDATE' будет преобразована в DATETIME (что, разумеется, завершится ошибкой).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...