tags:

views:

93

answers:

2

Hello,

I've checked the documentation for SCOPE_IDENTITY(), and it says "A scope is a module: a stored procedure, trigger, function, or batch." That is simple when I'm running a query in SSMSE, but in C# I'm using SqlCommand for executing my statements.

The question is: what is the scope there? Is executing subsequent commands under one connection an equivalent of batch? Or maybe every command is in a different scope and I need a transaction for this to work?

+5  A: 

I suggest thinking of your C# commands and T-SQL "Batches" as completely separate to one another.

Think of SQLCommand as your execution wrapper only, within which the actual definition of what constitutes a batch is defined and controlled by the T-SQL language.

Your session scope is maintained at the Connection object level.

You will likely find the following MSDN forum post interesting reading. Notice how the initial example executes two separate SQL Commands but the SCOPE_IDENITY() of the second call can see the result of the previous call. This is because the current scope is visible at the connection level.

SQLCommand With Parameters and Scope_Indentity

For completeness of explanation, the reason why this does not work using parameters, as later demonstrated in the linked example, is because sp_executesql is executed within it's own scope and so therefore cannot see the scope of the connection.

[EDIT]

Further reading for the more inquisitive reader, please find VB.NET code below that provides an example of executing two separate commands on a single Connection, with the second command sucessfully issuing the SCOPE_IDENTITY() function.

The source code can be executed from within the SCRIPT component of an SSIS package Task. You will also need to edit the connection details for your environment and also create the table object referenced.

Create Table Script:

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

VB.NET Source Listing:

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
John Sansom
@john, "this is because the scope is maintained/visible at the connection level." i am disagreeing with you.. the scope is determined by where you are specifying the scope_identity() in your query, in the linked example 1, in 2 queries different commands executed. since both are in different scope, it returns null... So the scope is with per command only.. not connection...
Ramesh Vel
@Ramesh Vel: Please find an edit to the original post to include source code that validates session scope visibility across two separate commands within a connection.
John Sansom
I've done almost the same kind of test, but in C# and executing SCOPE_IDENTITY() in separate commands works well even though I was inserting some more records to the table in between the call to insert and select scope_identity() (console application, ReadLine() between commands)
kubal5003
@Ramesh Vel: May I also suggest that you refrain from posting sweeping statements unless you are able to validate them. It's irresponsible as some readers will take your comments as gospel. Scope is not determined by where the SCOPE_IDENTITY() function is specified, it's positioning in the T-SQL code has no influence or control over the active session scope.
John Sansom
A: 

I believe scope is only applicable for the single command, not for the entire connection.

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

In The above code strSQL is a complete scope,and it always return the @@identity value of the associated insert statement.

so the subsequent commands will have its own scope.

Cheers

Ramesh Vel
I'm inclined to disagree with you.
John Sansom
@john, why is that so??
Ramesh Vel
@Ramesh Vel: The following example code would seem to suggest otherwise: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/080280b7-9c2d-4ee5-afe0-5c07d2affc7c
John Sansom
@John, did you check the complete query, SELECT SCOPE_IDENTITY() is inline, so this will be executed within a scope.. this approach ensures the scope_identity to run within the scope of the each command...
Ramesh Vel
@John, the link you have added also suggesting the same what i said...
Ramesh Vel
@Ramesh Vel: The source code you have posted is correct but is not what I am disputing. I'm disputing your point that subsequent commands executed on the same connection will have their own separate scope. That is not necessarily the case.
John Sansom
What I made of this is: usually scope is maintained for the connection. However there is an exception: if I use stored procedure(or it is used implicitly for me) then what is executed within has a different scope than the rest. Am I right?
kubal5003
@kubal5003, yes if you are using procedure, then the scope will be within the sp. if you are executing the multiple commands in a single connection, and the SELECT SCOPE_IDENTITY() as separate command the scope will be lost (means the result wont be expected).. use it inline if you wanted to get hold of the scope for your particular command...
Ramesh Vel
@Ramesh Vel: Tests suggest something else. If you can prove your point I'll be happy to see it.
kubal5003
@kubal5003: Correct, the session scope is visible to subsequent commands issued within the same session, provided scope visibility is not broken, for example when encapsulating a statement through the use of a command call such as sp_executeSQL.
John Sansom