SCOPE_IDENTITY в С# - диапазон

Я проверил документацию для SCOPE_IDENTITY(), и он говорит: "Область - это модуль: хранимая процедура, триггер, функция, или партия". Это просто, когда я запускаю запрос в SSMSE, но в С# я использую SqlCommand для выполнения моих операторов.

Вопрос в том, какова область действия? Выполняет ли последующие команды под одним соединением эквивалент пакета? Или, может быть, каждая команда находится в другом объеме, и мне нужна транзакция для этого?

Ответ 1

Я предлагаю подумать о том, что ваши команды С# и T-SQL "партии" полностью разделены друг с другом.

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

Область сеанса поддерживается на уровне объектов Connection.

Скорее всего, вы найдете следующее сообщение в форуме MSDN. Обратите внимание, как в первом примере выполняются две отдельные команды SQL, но SCOPE_IDENITY() второго вызова может видеть результат предыдущего вызова. Это связано с тем, что текущая область видимости видна на уровне соединения.

SQLCommand с параметрами и Scope_Indentity

Для полноты объяснения причина, по которой это не работает с использованием параметров, как показано позже в связанном примере, заключается в том, что sp_executesql выполняется в своей собственной области и поэтому не может видеть область соединения.

[EDIT]

Дальнейшее чтение для более любознательного читателя, пожалуйста, найдите приведенный ниже код VB.NET, который представляет пример выполнения двух отдельных команд в одном соединении, а вторая команда успешно выполняет функцию SCOPE_IDENTITY().

Исходный код может быть выполнен из компонента SCRIPT задачи пакета SSIS. Вам также нужно будет отредактировать детали подключения для вашей среды, а также создать связанный с ним объект таблицы.

Создать таблицу Script:

create table TestTable
(
    ID int identity(1,1) primary key not null,
    SomeNumericData int not null
);

Список версий VB.NET:

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.Data.SqlClient.SqlConnection
Imports Windows.Forms.MessageBox

Public Class ScriptMain



    Public Sub Main()
        '
        ' Add your code here

        Dim oCnn As New Data.SqlClient.SqlConnection
        Dim sSQL As String
        Dim sSQL2 As String
        Dim resultOne As Integer
        Dim resultTwo As Integer
        Dim messageBox As Windows.Forms.MessageBox

        resultOne = 0
        resultTwo = 0

        oCnn.ConnectionString = "Server=ServerName;Database=DatabaseName;Trusted_Connection=true"
        sSQL = "INSERT INTO TestTable(SomeNumericData) VALUES(666) "
        sSQL2 = "SELECT SCOPE_IDENTITY()"
        Dim oCmd As SqlClient.SqlCommand = New SqlClient.SqlCommand(sSQL, oCnn)
        Dim oCmd2 As SqlClient.SqlCommand = New SqlClient.SqlCommand(sSQL2, oCnn)

        oCmd.CommandType = CommandType.Text
        oCmd.Connection = oCnn
        oCnn.Open()

        resultOne = oCmd.ExecuteNonQuery()
        resultTwo = Convert.ToInt32(oCmd2.ExecuteScalar())

        oCnn.Close()

        messageBox.Show("result1:" + resultOne.ToString + Environment.NewLine + "result2: " + resultTwo.ToString)

        Dts.TaskResult = Dts.Results.Success
    End Sub
End Class

Ответ 2

Я считаю, что область видимости применима только для одной команды, а не для всего соединения.

strSQL = "INSERT INTO tablename (name) VALUES (@name);SELECT SCOPE_IDENTITY()"
SQLCommand.CommandText = strSQL
Id = SQLCommand.ExecuteScalar()

В приведенном выше коде strSQL - полная область действия, и она всегда возвращает значение @@идентификатора связанной инструкции insert.

поэтому последующие команды будут иметь свою собственную область.