2010-10-12 17 views
10

He comprobado la documentación para SCOPE_IDENTITY(), y dice "Un ámbito es un módulo: un procedimiento almacenado, disparador, función o lote". Eso es simple cuando estoy ejecutando una consulta en SSMSE, pero en C# estoy usando SqlCommand para ejecutar mis declaraciones.SCOPE_IDENTITY en C# - rango

La pregunta es: ¿cuál es el alcance allí? ¿Está ejecutando comandos subsiguientes bajo una conexión un equivalente de lote? O tal vez cada comando tiene un alcance diferente y necesito una transacción para que esto funcione.

Respuesta

7

Sugiero pensar en sus comandos C# y T-SQL "Lotes" como completamente separados entre sí.

Piense en SQLCommand como su envoltorio de ejecución solamente, dentro del cual la definición real de lo que constituye un lote está definida y controlada por el lenguaje T-SQL.

El alcance de su sesión se mantiene en el nivel del objeto Connection.

Es probable que la siguiente publicación en el foro de MSDN le resulte interesante. Observe cómo el ejemplo inicial ejecuta dos comandos SQL separados, pero SCOPE_IDENITY() de la segunda llamada puede ver el resultado de la llamada anterior. Esto se debe a que el alcance actual es visible en el nivel de conexión.

SQLCommand With Parameters and Scope_Indentity

Para completar la explicación, la razón por la que esto no funciona utilizando parámetros, como más tarde se demostró en el ejemplo enlazado, se debe a sp_executesql se ejecuta dentro de su propio ámbito de aplicación y por lo tanto no puede ver el alcance de la conexión.

[EDIT]

Lectura adicional para el lector más curioso, por favor, encontrar el código VB.NET a continuación que proporciona un ejemplo de ejecución de dos comandos separados en una única conexión, con el segundo comando de emisión con éxito la SCOPE_IDENTITY() función.

El código fuente se puede ejecutar desde el componente SCRIPT de un paquete SSIS Tarea. También necesitará editar los detalles de conexión para su entorno y también crear el objeto de tabla al que se hace referencia.

crear tabla Guión:

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

VB.NET Fuente de listado:

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 
+0

"esto es porque el alcance se mantiene/visible en el nivel de conexión." No estoy de acuerdo con usted. El alcance está determinado por el lugar donde especifica el scope_identity() en su consulta, en el ejemplo 1 vinculado, en 2 consultas ejecutadas diferentes comandos. dado que ambos tienen un alcance diferente, devuelve nulo ... Entonces el alcance es solo por comando ... no conexión ... – RameshVel

+0

@Ramesh Vel: busque una edición en la publicación original para incluir el código fuente que valida la visibilidad del alcance de la sesión en dos comandos separados dentro de una conexión. –

+0

He hecho casi el mismo tipo de prueba, pero en C# y ejecutar SCOPE_IDENTITY() en comandos separados funciona bien aunque estaba insertando más registros en la tabla entre la llamada para insertar y seleccionar scope_identity() (aplicación de consola , ReadLine() entre comandos) – kubal5003

1

Creo ámbito sólo es aplicable para el mando único, no para toda la conexión.

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

en el código anterior strSQL es un ámbito de aplicación completa, y siempre devuelven el valor de identidad @@ de la instrucción de inserción asociada.

por lo que los comandos posteriores tendrán su propio alcance.

+0

Me inclino a estar en desacuerdo contigo. –

+0

@john, ¿por qué es eso? – RameshVel

+0

@ Ramesh Vel: El siguiente código de ejemplo parecería sugerir lo contrario: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/080280b7-9c2d-4ee5-afe0-5c07d2affc7c –

Cuestiones relacionadas