交易(进程ID)陷入僵局

时间:2015-07-21 10:52:11

标签: sql asp.net sql-server asp.net-mvc entity-framework-6

我有一个悲观并发的应用程序锁,并在Asp.Net Mvc中生成代码。

using (var scope = new TransactionScope())
{
      using (var context = new Context())
      {
           var submitedEntity = context.Entities.Add(entity);
           context.SaveChanges();
           context.Entry(submitedEntity).Reload();
           code = submitedEntity.Code;

           scope.Complete();
      }
}

在SQL Server Trigger中生成代码

Create  Trigger     [dbo].[OnInsertEntity]
On  [dbo].[TableName]
After   Insert
As
Begin
Begin   Transaction
    Declare @ID     BigInt,
        @LastCode   Int,
        @Length     Int,
        @Code       nChar(5)

Select  @ID     = ID
    From    Inserted

Select  @LastCode   = Max(Convert(Int, Code))
    From    [TableName]
    With    (TABLOCKX, HOLDLOCK)

If  @@RowCount      = 0
    Set @LastCode   = 0

Waitfor Delay '00:00:05'

Select  @Length     = Max_Length
    From    Sys.Columns
    Where   Name        = N'Code'   And
        [Object_ID] = Object_ID('[TableName]')

Select  @LastCode   = @LastCode + 1,
    @Code       = Replicate('0', @Length - Len(@LastCode)) + Convert(nChar, @LastCode)


Update  [TableName]
    Set Code    = @Code
    Where   ID  = @ID
Commit  Transaction
End

错误:

catch (DbUpdateException ex)
  

事务(进程ID)在锁定资源上与另一个进行了死锁   进程并被选为死锁受害者。重新运行该交易。

有什么问题?

感谢。

1 个答案:

答案 0 :(得分:0)

如果我正确理解您的代码,您似乎只是尝试将正在运行的数字更新到每一行,而它实际上是一个包含前导零的nchar字段。

在整个桌子上使用带独占锁定的触发器等听起来不错。我宁愿建议你在表格中使用标识字段。如果你真的需要一个前导零,我只需要在表中添加一个计算列,该列使用编号的标识字段。