2015-07-21 135 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字段。

對整個表格使用獨佔鎖定觸發器等聽起來像個壞主意。我寧願推薦你在表中使用身份字段。如果你確實需要一個前導零,那麼我只需將計算列添加到使用標識字段進行編號的表中。

相關問題