#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 или нет, поскольку это является его предназначением — поскольку вы фактически не используете количество затронутых строк для чего-либо еще.