2010-10-12 15 views
10

Ho controllato la documentazione per SCOPE_IDENTITY() e dice "Un ambito è un modulo: una stored procedure, trigger, funzione o batch." È semplice quando eseguo una query in SSMSE, ma in C# sto usando SqlCommand per l'esecuzione delle mie istruzioni.SCOPE_IDENTITY in C# - range

La domanda è: qual è lo scopo lì? L'esecuzione di comandi successivi in ​​una connessione equivale a un batch? O forse ogni comando ha una portata diversa e ho bisogno di una transazione per far funzionare tutto questo?

risposta

7

Suggerisco di pensare ai comandi C# e ai "lotti" T-SQL completamente separati l'uno dall'altro.

Pensa a SQLCommand solo come wrapper di esecuzione, all'interno del quale la definizione effettiva di ciò che costituisce un batch è definita e controllata dal linguaggio T-SQL.

L'ambito della sessione viene gestito a livello di oggetto Connessione.

È probabile che il seguente forum MSDN pubblichi una lettura interessante. Notare come l'esempio iniziale esegue due comandi SQL separati ma SCOPE_IDENITY() della seconda chiamata può vedere il risultato della chiamata precedente. Questo perché l'ambito corrente è visibile a livello di connessione.

SQLCommand With Parameters and Scope_Indentity

Per completezza di esposizione, la ragione per cui questo non funziona utilizzando parametri, come successivamente illustrato nell'esempio legato, è perché sp_executesql viene eseguito entro il proprio campo di applicazione e quindi non può quindi vedere la portata della connessione.

[EDIT]

Ulteriore lettura per il lettore più curioso, trova prego codice VB.NET sotto riportato un esempio di esecuzione di due comandi separati una singola connessione, con il secondo comando con successo rilascia la SCOPE_IDENTITY() funzione.

Il codice sorgente può essere eseguito all'interno del componente SCRIPT di un pacchetto SSIS Attività. Sarà inoltre necessario modificare i dettagli della connessione per il proprio ambiente e creare anche l'oggetto tabella a cui si fa riferimento.

Crea tabella Script:

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

VB.NET Listing Fonte:

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

"questo perché l'ambito viene mantenuto/visibile a livello di connessione". non sono d'accordo con te .. l'ambito è determinato da dove stai specificando scope_identity() nella tua query, nell'esempio collegato 1, in 2 query comandi diversi eseguiti. dal momento che entrambi sono in scope differenti, restituisce null ... Quindi l'ambito è solo per comando .. non per connessione ... – RameshVel

+0

@Ramesh Vel: trovare una modifica al post originale per includere il codice sorgente che convalida la visibilità dell'ambito della sessione attraverso due comandi separati all'interno di una connessione. –

+0

Ho eseguito quasi lo stesso tipo di test, ma in C# e l'esecuzione di SCOPE_IDENTITY() in comandi separati funziona bene anche se inserivo altri record nella tabella tra la chiamata da inserire e selezionare scope_identity() (applicazione console , ReadLine() tra i comandi) – kubal5003

1

Credo campo di applicazione è applicabile solo per il singolo comando, non per l'intero collegamento.

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

nel codice sopra strSQL è un campo di applicazione completa, e ritornano sempre il valore @@ identità della dichiarazione dell'inserto associato.

in modo che i comandi successivi abbiano il proprio ambito.

+0

Sono propenso a non essere d'accordo con te. –

+0

@john, perché è così ?? – RameshVel

+0

@Ramesh Vel: il seguente codice di esempio sembra suggerire diversamente: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/080280b7-9c2d-4ee5-afe0-5c07d2affc7c –