2010-10-12 3 views
10

J'ai vérifié la documentation de SCOPE_IDENTITY(), et il est écrit "Une portée est un module: une procédure stockée, un déclencheur, une fonction ou un lot". C'est simple quand j'exécute une requête dans SSMSE, mais en C# j'utilise SqlCommand pour exécuter mes instructions.SCOPE_IDENTITY en C# - plage

La question est: quelle est la portée là? Est-ce que l'exécution de commandes ultérieures sous une connexion équivaut à un traitement par lots? Ou peut-être que chaque commande est dans une portée différente et j'ai besoin d'une transaction pour que cela fonctionne?

Répondre

7

Je suggère de penser à vos commandes C# et aux "lots" T-SQL comme étant complètement séparés les uns des autres. Pensez à SQLCommand comme votre enveloppe d'exécution uniquement, dans laquelle la définition réelle de ce qui constitue un lot est définie et contrôlée par le langage T-SQL.

Votre étendue de session est gérée au niveau de l'objet Connexion.

Vous trouverez probablement le forum MSDN suivant une lecture intéressante. Notez comment l'exemple initial exécute deux commandes SQL distinctes, mais le SCOPE_IDENITY() du second appel peut voir le résultat de l'appel précédent. C'est parce que la portée actuelle est visible au niveau de la connexion.

SQLCommand With Parameters and Scope_Indentity

Pour être complet d'explication, la raison pour laquelle cela ne fonctionne pas à l'aide des paramètres, comme l'a démontré plus tard dans l'exemple lié, est parce que sp_executesql est exécuté dans son propre champ d'application et donc ne peut donc pas voir la portée de la connexion.

[EDIT]

Pour en savoir plus pour le lecteur plus curieux, s'il vous plaît trouver le code VB.NET ci-dessous qui fournit un exemple d'exécuter deux commandes séparées sur une seule connexion, avec la deuxième commande l'émission du SCOPE_IDENTITY sucessfully() fonction.

Le code source peut être exécuté à partir du composant SCRIPT d'une tâche de package SSIS. Vous devrez également modifier les détails de connexion pour votre environnement et également créer l'objet de table référencé.

Créer un script de table:

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

VB.NET Source Liste:

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

"C'est parce que la portée est maintenue/visible au niveau de la connexion." Je suis en désaccord avec vous .. la portée est déterminée par où vous spécifiez le scope_identity() dans votre requête, dans l'exemple 1 lié, dans 2 requêtes différentes commandes exécutées. puisque les deux sont dans une portée différente, elle renvoie null ... Donc la portée est avec per command seulement .. pas de connexion ... – RameshVel

+0

@Ramesh Vel: Veuillez trouver une modification apportée au message d'origine afin d'inclure le code source qui valide la visibilité de la portée de session sur deux commandes distinctes au sein d'une connexion. –

+0

J'ai fait presque le même genre de test, mais en C# et en exécutant SCOPE_IDENTITY() dans des commandes séparées fonctionne bien même si j'insérais plus d'enregistrements sur la table entre l'appel à insérer et sélectionnez scope_identity() , ReadLine() entre les commandes) – kubal5003

1

Je crois que la portée est applicable uniquement pour la commande unique, pas pour toute la connexion.

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

Dans le code ci-dessus strSQL est un champ complet, et toujours retourner la valeur d'identité @@ de l'instruction d'insertion associée. Ainsi, les commandes suivantes auront leur propre portée.

+0

Je suis enclin à ne pas être d'accord avec vous. –

+0

@john, pourquoi est-ce donc? – RameshVel

+0

@Ramesh Vel: L'exemple de code suivant semble suggérer le contraire: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/080280b7-9c2d-4ee5-afe0-5c07d2affc7c –

Questions connexes