如何编写线程安全的SQL Server存储过程

时间:2015-08-26 06:00:02

标签: c# sql-server

我有一些存储过程,其中正在执行多个查询。为了得到插入的最后一个身份我正在使用IDENT_CURRENT这是因果问题。

我的问题是我可以在T-SQL中使用像C#这样的锁定语句,以便它可以是线程安全的吗?

编辑:我正在使用的代码

INSERT INTO activities
    (creator
    ,title
    ,description)
VALUES
    (@Creator
    ,@Tile
    ,@Description)

SET @ActivityId = IDENT_CURRENT('dbo.activities');

INSERT INTO [dbo].activity_cfs
    ([activity_id],
    [cf_id],
    [cf_field_name],
    [field_key],
    [value])
SELECT 
    @ActivityId,
    cf_id,
    cf_field_name,
    field_key,
    value
FROM @ActivityCustomFields 

@ActivityCustomFields是我的临时表。

1 个答案:

答案 0 :(得分:5)

您很可能应该使用SCOPE_IDENTITY而不是SCOPE_IDENTITY。有许多解释如何区别,例如:What is the difference between Scope_Identity(), Identity(), @@Identity, and Ident_Current?

但是,如果您确实需要保证代码的某些部分不会同时由多个线程运行,则可以使用sp_getapplock

根据您添加到问题中的代码,我现在非常确定您应该只使用INSERT INTO activities (creator ,title ,description) VALUES (@Creator ,@Tile ,@Description); SET @ActivityId = SCOPE_IDENTITY(); INSERT INTO [dbo].activity_cfs ([activity_id], [cf_id], [cf_field_name], [field_key], [value]) SELECT @ActivityId, cf_id, cf_field_name, field_key, value FROM @ActivityCustomFields; ,如下所示:

SCOPE_IDENTITY

IDENT_CURRENT函数返回在同一会话和相同范围内创建的最后一个标识。 IDENT_CURRENT返回在任何会话中为特定表或视图创建的最后一个标识。因此,如果您有多个线程同时运行此过程,_request.AddJsonBody(obj1); _request.AddJsonBody(obj2); 将会看到其他线程中生成的身份,您不需要。