C# 类似于SQL Server中的LOCK语句

C# 类似于SQL Server中的LOCK语句,c#,sql,.net,sql-server,C#,Sql,.net,Sql Server,我需要在C#中生成类似于lock语句的东西,这是一个可以包含多个操作的同步作用域。假设我有一个表GeneratedKeys,用于跟踪数据库为其他一些表生成的所有会话密钥。它有一个主键列[key]和一个用户定义的自定义函数dbo.GenerateKey(),可以生成下一个随机键。我只想插入唯一的密钥,因此我必须验证生成的密钥的唯一性,因此我必须重新生成它,直到它变得唯一为止。这需要一个同步的块,因为这里发生了多个操作。我的做法: WHILE (1 = 1) BEGIN DECLARE @n

我需要在C#中生成类似于lock语句的东西,这是一个可以包含多个操作的同步作用域。假设我有一个表
GeneratedKeys
,用于跟踪数据库为其他一些表生成的所有会话密钥。它有一个主键列
[key]
和一个用户定义的自定义函数
dbo.GenerateKey()
,可以生成下一个随机键。我只想插入唯一的密钥,因此我必须验证生成的密钥的唯一性,因此我必须重新生成它,直到它变得唯一为止。这需要一个同步的块,因为这里发生了多个操作。我的做法:

WHILE (1 = 1)
 BEGIN
   DECLARE @newKey CHAR(10) = dbo.GenerateKey();
   DECLARE @existingKey CHAR(10) = NULL;

   SELECT TOP 1 @existingKey = [entry].[Key]
   FROM [dbo].[GeneratedKeys] [entry] WITH (TABLOCKX, HOLDLOCK)
   WHERE [entry].[Key] = @newKey

   -- go to re-generate if matched
   IF @existingKey IS NOT NULL 
         CONTINUE;

   -- insert only a unique key 
   INSERT INTO [dbo].[GeneratedKeys]([Key], [CreatedOnUtc])
      OUTPUT [INSERTED].[Key] [Key]
   SELECT @newKey, GETUTCDATE()

   BREAK;
END

我的问题是-我是否选择了正确的锁定提示组合?首先,获取整个表的
TABLOCKX
独占锁,并使用
HOLDLOCK

将其扩展到剩余块的末尾。我们遵循以下方法,以确保当有多个并发请求到达数据库时,只执行一个请求。基本上,这就像在C#中模拟锁场景一样


我知道这可能不是一个完美的解决方案,但它对我的情况有效。请小心使用锁,否则会导致死锁。

将其包装在事务中,并移除
holdlock
-独占表锁将在其所在事务的持续时间内保持。无需费心去做所有这些,只需使用几乎可以保证是唯一的。您可以只在键列上放置一个唯一索引,让插入失败,然后重试。为什么不只使用标识列呢?它每次都生成唯一的数字。我只需要字符串,不需要数字
CREATE PROCEDURE [dbo].[GetSequenceNumber]
AS
BEGIN
    SET NOCOUNT ON
    BEGIN TRANSACTION
    BEGIN TRY

            UPDATE [Rcon.Drawing].[dbo].[TableForLock] WITH (UPDLOCK) set LockValue = LockValue where LockName = 'Dummy'

        -- Logic to generate the next sequence number based on the existing value in the database

        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
            ROLLBACK TRANSACTION
            PRINT ERROR_NUMBER()
            PRINT ERROR_MESSAGE()
    END CATCH
END