2015-07-21 94 views
1

我有一个悲观并发的应用程序锁,并在Asp.Net Mvc中生成代码。事务(进程ID)被锁死

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触发生成代码在

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)已被死锁的锁资源与另一个 过程,并已被选为死锁受害者。重新运行交易。

什么问题?

谢谢。

+0

OUCH,tablockx + waitfor延迟触发器。 –

+0

除此之外,您的逻辑中存在严重缺陷,插入/更新完成多行时,SQL Server中插入和删除的表可以(且将会)包含多行 –

+0

Waitfor Delay '00:00: 05'这是为了测试悲观并发 –

回答

0

如果我正确理解你的代码,它看起来像你只是试图更新每行的运行号码,它实际上是一个包含前导零的nchar字段。

对整个表格使用独占锁定触发器等听起来像个坏主意。我宁愿推荐你在表中使用身份字段。如果你确实需要一个前导零,那么我只需将计算列添加到使用标识字段进行编号的表中。

相关问题