c#-范围为_identity()的并发插入
我们有十几个客户端,它们使用一个程序集以简单SQL语句的形式将数据插入我的SQL Server 2012 有两个带有标识列和外键的表(例如c#-范围为_identity()的并发插入,c#,sql-server,concurrency,scope,C#,Sql Server,Concurrency,Scope,我们有十几个客户端,它们使用一个程序集以简单SQL语句的形式将数据插入我的SQL Server 2012 有两个带有标识列和外键的表(例如[User]和[Location]) 语句的执行总是相同的:createuser,将新id另存为创建位置的外键 在伪代码中: //open DB Connection Connection.Open(); //Insert user "INSERT INTO User (Name, Birthdate) VALUES ("Smith", "1.1.1919"
[User]
和[Location]
)
语句的执行总是相同的:createuser,将新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\u IDENTITY()
是否有可能检索另一个客户端/线程创建的用户的新创建ID
特别是在插入用户和Scope\u Identity()
OUTPUT
子句可能是澄清问题的另一种选择吗
会话
对应于您与数据库的当前连接(Ado.Net/EF/SSMS等)。一个应用程序可能有多个到数据库的会话
范围是执行SQL命令的上下文。假设您调用某个T-SQL,它调用一个存储过程,执行某个触发器。T-SQL将有一个作用域,然后是存储过程中代码的另一个嵌套作用域,然后是触发器中代码的另一个作用域。因此,当您使用时,您正在检索您所在范围内最后插入的PK Id
本质上,不同的会话意味着不同的范围
相反,返回会话中最后插入的ID。它没有“范围感知”。如果您在表中插入,并且触发器在幕后执行某些操作,则有机会获得触发器插入的ID
请注意,如果回滚已生成PK Id的事务,则PK计数器不会返回到上一个值,因为回滚,该行不会提交,但会存在一个小漏洞—表PK连续性…SCOPE\u IDENTITY
是作用域内的标识。因此,具有不同作用域的并发连接不会重叠。因此,如果每个连接在db上都有自己的作用域,那么作用域和会话之间有什么区别呢?感谢您的解释!第三种可能性是IDENT_CURRENT
,它将返回任何会话和任何作用域上的特定表的值-对于我的应用程序来说,这并不是真正正确的事情。有一点“非常明显”的事情我忘了说:作用域(ex的存储过程)不会在不同会话之间共享,也不会在不同调用之间共享。如果在同一会话中并行调用同一SP 16次,它将创建不同的16个作用域