c# - 使用 Scope_Identitiy() 的并发插入
c# - concurrent inserts with Scope_Identitiy()
我们有十几个客户使用程序集以简单的 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()
检索新创建的 ID User
由另一个 client/thread?
创建
特别是在插入用户和 Scope_Identity()
之间是否有时间让另一个线程插入 Scope_Identity
读取的新用户?
也许 OUTPUT
子句可以替代?
澄清事情
A session
对应于您与数据库的当前连接(Ado.Net / EF / SSMS 等)。一个应用程序可能与一个数据库有多个会话。
A scope
是执行 SQL 命令的上下文。想象一下,您调用一些 T-SQL,它调用一个存储过程,它执行一些触发器。您的 T-SQL 将有一个作用域,然后是存储过程内代码的另一个嵌套作用域,然后是触发器内代码的另一个作用域。因此,当您使用 SCOPE_IDENTITY
时,您正在检索您所在范围内最后插入的 PK Id。
本质上,不同的会话意味着不同的范围。
相反,@@IDENTITY
returns 会话中最后插入的 ID。这不是 "scope-aware"。如果您插入 table,并且触发器在幕后执行某些操作,您就有机会获得触发器插入的 ID。
请注意,如果您回滚已生成 PK Id 的事务,PK 计数器不会返回到以前的值,因为回滚,该行未提交,但会存在一个小洞table PK连续性...
我们有十几个客户使用程序集以简单的 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()
检索新创建的 ID User
由另一个 client/thread?
特别是在插入用户和 Scope_Identity()
之间是否有时间让另一个线程插入 Scope_Identity
读取的新用户?
也许 OUTPUT
子句可以替代?
澄清事情
A session
对应于您与数据库的当前连接(Ado.Net / EF / SSMS 等)。一个应用程序可能与一个数据库有多个会话。
A scope
是执行 SQL 命令的上下文。想象一下,您调用一些 T-SQL,它调用一个存储过程,它执行一些触发器。您的 T-SQL 将有一个作用域,然后是存储过程内代码的另一个嵌套作用域,然后是触发器内代码的另一个作用域。因此,当您使用 SCOPE_IDENTITY
时,您正在检索您所在范围内最后插入的 PK Id。
本质上,不同的会话意味着不同的范围。
相反,@@IDENTITY
returns 会话中最后插入的 ID。这不是 "scope-aware"。如果您插入 table,并且触发器在幕后执行某些操作,您就有机会获得触发器插入的 ID。
请注意,如果您回滚已生成 PK Id 的事务,PK 计数器不会返回到以前的值,因为回滚,该行未提交,但会存在一个小洞table PK连续性...