2010-10-12 21 views
10

Sprawdziłem dokumentację dla SCOPE_IDENTITY() i napisano "Zakres to moduł: procedura składowana, wyzwalacz, funkcja lub partia." To proste, gdy uruchamiam zapytanie w SSMSE, ale w języku C# używam SqlCommand do wykonywania moich instrukcji.SCOPE_IDENTITY w języku C# - zakres

Pytanie brzmi: jaki jest zakres? Czy kolejne polecenia w ramach jednego połączenia są równoważne wsadowi? A może każde polecenie ma inny zakres i potrzebuję transakcji, aby to zadziałało?

Odpowiedz

7

Proponuję, aby twoje komendy C# i T-SQL "partie" były całkowicie od siebie oddzielone.

Wyobraź sobie, że SQLCommand jest tylko opakowaniem wykonawczym, w ramach którego rzeczywistą definicję tego, co składa się na partię, definiuje się i kontroluje za pomocą języka T-SQL.

Twój zakres sesji jest utrzymywany na poziomie obiektu Połączenia.

Prawdopodobnie na poniższym stanowisku MSDN post pojawi się interesująca lektura. Zwróć uwagę, że początkowy przykład wykonuje dwa oddzielne polecenia SQL, ale funkcja SCOPE_IDENITY() drugiego połączenia może zobaczyć wynik poprzedniego połączenia. Dzieje się tak, ponieważ bieżący zakres jest widoczny na poziomie połączenia.

SQLCommand With Parameters and Scope_Indentity

Dla kompletności wyjaśnienia, powód dlaczego to nie działa za pomocą parametrów, jak później wykazano w połączonej przykład dlatego sp_executesql jest wykonywana w jego własnym zakresie i tak więc nie widzę zakresu wynalazku połączenie.

[Edycja]

Dalsze odczytu dla dociekliwsza czytnika można znaleźć kod VB.NET poniżej przedstawia przykład wykonania dwa oddzielne polecenia na pojedynczego połączenia, przy czym drugie polecenie powodzeniem wystawienia SCOPE_IDENTITY() Funkcja.

Kod źródłowy można wykonać z poziomu komponentu SCRIPT zadania pakietu SSIS. Będziesz także musiał edytować szczegóły połączenia dla swojego środowiska, a także utworzyć obiekt tabeli, do którego się odwołujesz.

Utwórz skrypt tabeli:

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

VB.NET nieruchomość Źródło:

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

"dzieje się tak, ponieważ zakres jest utrzymany/widoczny na poziomie połączenia." nie zgadzam się z tobą. Zakres jest określony przez miejsce, w którym określasz parametr scope_identity() w zapytaniu, w połączonym przykładzie 1, w 2 kwerendach wykonanych różnych poleceń. ponieważ oba są w różnym zakresie, zwraca wartość null ... Tak więc zakres dotyczy tylko polecenia ... nie połączenia ... – RameshVel

+0

@Ramesh Vel: znajdź edycję oryginalnego wpisu, aby dołączyć kod źródłowy, który sprawdza poprawność widoczności zakresu sesji przez dwa oddzielne polecenia w obrębie połączenia. –

+0

Zrobiłem prawie ten sam rodzaj testu, ale w C# i wykonanie SCOPE_IDENTITY() w osobnych poleceniach działa dobrze, mimo że wstawiłem kilka rekordów do tabeli pomiędzy wywołaniem wstawić i wybrać scope_identity() (aplikacja konsoli , ReadLine() między poleceniami) – kubal5003

1

wierzę zakres ma zastosowanie tylko do jednego polecenia, a nie dla całego połączenia.

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

w powyższym kodzie strSQL to kompletny zakres, a to zawsze zwraca wartość @@ tożsamości skojarzonego INSERT.

, więc kolejne polecenia będą miały własny zakres.

+0

Jestem skłonny się z tobą nie zgodzić. –

+0

@john, dlaczego tak jest? – RameshVel

+0

@Ramesh Vel: Poniższy kod przykładowy sugeruje inaczej: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/080280b7-9c2d-4ee5-afe0-5c07d2affc7c –