c# - 使用Scope_Identitiy()进行并发插入

时间:2015-02-17 20:30:12

标签: c# sql-server concurrency scope

我们有十几个客户端使用程序集以简单的SQL语句的形式将数据插入到我的SQL Server 2012中。

有两个表(例如[User][Location]),其中包含标识列和外键。

语句的执行始终相同:创建用户,将新id保存为用于创建位置的外键。

在伪代码中:

//open DB Connection
Connection.Open();

//Insert user
"INSERT INTO User (Name, Birthdate) VALUES ("Smith", "1.1.1919");
 SELECT SCOPE_IDENTITY();" //save the new ID in var "newID"

//Execute Statement
ExecuteQuery();

//Insert Location
"INSERT INTO Location(Country, City, User_ID) VALUES ("Germany", "Cologne", newID)"

//Execute Statement
ExecuteQuery();

//close Connection
Connection.Close();

在此之前没有魔力......但是如果我在多个客户端或并行线程上同时运行此代码,SCOPE_IDENTITY()可能会检索User的新创建的ID由另一个客户/线程创建?

特别是在插入用户和Scope_Identity()之间有另一个线程来插入Scope_Identity读取的新用户吗?

可能是OUTPUT条款的另一种选择吗?

1 个答案:

答案 0 :(得分:2)

澄清事情

session对应于您对数据库的当前连接(Ado.Net / EF / SSMS等)。应用程序可能有多个数据库会话。

scope是执行SQL命令的上下文。想象一下,你调用一些调用存储过程的T-SQL,它执行一些触发器。您的T-SQL将有一个范围,然后是存储过程中代码的另一个嵌套范围,然后是触发器内代码的另一个范围。因此,当您使用SCOPE_IDENTITY时,您将在您所在的范围内检索最后插入的PK Id。

本质上,不同的会话意味着不同的范围。

相反,@@IDENTITY返回会话中最后插入的ID。它不是"范围感知"。如果您在表格中插入,并且触发器在场景后面执行某些操作,则您有机会通过触发器插入ID。

请注意,如果您回滚已生成PK Id的事务,则PK计数器不会返回到先前的值,因为回滚而没有提交该行,但是会存在一个小漏洞表PK连续性......