Инструкции вставки и обновления хранимой процедуры работают, но затронутые строки равны -1?

#sql #sql-server #vb.net #stored-procedures #ado.net

#sql #sql-сервер #vb.net #хранимые процедуры #ado.net

Вопрос:

Я работаю над программой, которая может добавлять спонсоров через программу VB. Мои хранимые процедуры добавления и обновления спонсора работают, когда я тестирую их в SQL, но обе выдают ошибку, потому что затронутые строки возвращают значение -1. Однако, когда я просматриваю свою базу данных, вставка / обновление ДЕЙСТВИТЕЛЬНО сработали. Кто-нибудь может помочь мне выяснить, почему затронутые строки возвращают значение -1, если вставка сработала?

Это возвращает -1 для обеих хранимых процедур. Вот код для добавления спонсора:

SQL:

 GO

CREATE PROCEDURE uspAddSponsor
    @intSponsorID AS INTEGER OUTPUT
   ,@strFirstName AS VARCHAR(50)
   ,@strLastName AS VARCHAR(50)
   ,@strStreetAddress AS VARCHAR(50)
   ,@strCity AS VARCHAR(50)
   ,@strState AS VARCHAR(50)
   ,@strZip AS VARCHAR(50)
   ,@strPhoneNumber AS VARCHAR(50)
   ,@strEmail AS VARCHAR(50)

AS 
SET NOCOUNT ON      --Report only errors
SET XACT_ABORT ON   --Terminate and rollback transaction on error

BEGIN TRANSACTION

    INSERT INTO TSponsors WITH (TABLOCKX) (strFirstName, strLastName, strStreetAddress, strCity, strState, strZip, strPhoneNumber, strEmail)
    VALUES               (@strFirstName, @strLastName, @strStreetAddress, @strCity, @strState, @strZip, @strPhoneNumber, @strEmail)

    SELECT @intSponsorID = MAX(intSponsorID) FROM TSponsors

COMMIT TRANSACTION

GO
  

VB-КОД:

 Private Sub AddSponsor(ByVal strFirstName As String, ByVal strLastName As String, ByVal strAddress As String, ByVal strCity As String, ByVal strState As String, ByVal strZip As String, ByVal strPhoneNumber As String, ByVal strEmail As String)
    Dim intRowsAffected As Integer
    Dim cmdAddSponsor As New OleDb.OleDbCommand()
    Dim intPKID As Integer

    Try
        'Open DB
        If OpenDatabaseConnectionSQLServer() = False Then

            ' No, warn the user ...
            MessageBox.Show(Me, "Database connection error." amp; vbNewLine amp;
                                "The application will now close.",
                                Me.Text   " Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error)

            ' and close the form/application
            Me.Close()
        End If

        'Text to call stored procedure
        cmdAddSponsor.CommandText = "EXECUTE uspAddSponsor '" amp; intPKID amp; "','" amp; strFirstName amp; "','" amp; strLastName amp; "','" amp; strAddress amp; "','" amp; strCity amp; "','" amp; strState amp; "','" amp; strZip amp; "','" amp; strPhoneNumber amp; "','" amp; strEmail amp; "'"
        cmdAddSponsor.CommandType = CommandType.StoredProcedure

        'Call stored procedure which will insert the record
        cmdAddSponsor = New OleDb.OleDbCommand(cmdAddSponsor.CommandText, m_conAdministrator)

        'This return is the # of rows affected
        intRowsAffected = cmdAddSponsor.ExecuteNonQuery()

        'Close DB
        CloseDatabaseConnection()

        'Let user know what happened
        If intRowsAffected > 0 Then
            MessageBox.Show("Sponsor successfully added")
        Else
            MessageBox.Show("Sponsor not added. Error")
        End If

        Close()

    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Close()
    End Try
End Sub

  

Есть идеи?

Комментарии:

1.Видите это SET NOCOUNT ON ? Это означает «не возвращать количество затронутых строк». Это обычная оптимизация (она экономит дополнительные сетевые поездки туда и обратно), но, очевидно, бесполезна, если вы действительно хотите, чтобы количество затронутых строк было изменено. Обычно, что вы должны сделать, это предположить, что sproc сработал правильно, если он не сгенерировал ошибку (что в данном случае сработало бы нормально, тем более что он использует XACT_ABORT ON и есть выходной параметр).

2. Это имеет смысл, большое спасибо!

3. @jenniferjonas Я бы настоятельно рекомендовал использовать надлежащие объекты SqlParameter для передачи ваших параметров в вашу хранимую процедуру вместо создания динамической строки. Параметры защищают вас от внедрения, гарантируют правильность типа данных и многое другое.

4. Прекратите использовать табличные подсказки, пока не наберетесь гораздо большего опыта, не поймете их эффект и не определите вескую причину для их использования. Предположительно, в вашей таблице есть столбец identity — если это так, гораздо лучше использовать предложение output или scope_identity() для извлечения значения, сгенерированного для вашей строки.

5. Может помочь следующее, SP Insert , внутренний код . Смотрите также статью TechNet

Ответ №1:

Согласно официальным документам

Когда в соединении установлено значение SET NOCOUNT ON (до или как часть выполнения команды, или как часть триггера, инициируемого выполнением команды), строки, на которые влияют отдельные инструкции, перестают вносить вклад в количество затронутых строк, возвращаемое этим методом.

Я предлагаю использовать возвращаемое значение SP, чтобы указать, сработал SP или нет, поскольку это является его предназначением — поскольку вы фактически не используете количество затронутых строк для чего-либо еще.