0

興味深いシナリオに出くわしました。Entity Framework で利用可能な context.database.sqlquery を使用して、ストアド プロシージャを呼び出してフィールドを更新しています。

Management Studio でプロシージャを直接呼び出すと、2 つ以上のアイテムを編集するときにデッドロックが発生しません。

context.database.sqlquery を使用して同じストアド プロシージャを呼び出すと、2 つ以上のアイテムを編集するときにロック解除が発生します。

これを修正する方法を見つけましたが、フレームワークからプロシージャを呼び出すとデッドロックが発生する理由がわかりません。それで聞いてみようと思いました。

--Create a temp table to hold items based on userid
CREATE TABLE #tableA
(   
    [Id] int identity (1,1),
    [Item_Id] int
)

INSERT INTO #tableA ([Item_Id]) SELECT [Id] FROM [Items] WHERE [UserId] = @UserId

--All of the other processing is omitted for brevity

--Based on final processing above update the IsActive flag on the Items table
UPDATE i
SET [IsActive] = 0
FROM #tableA ta INNER JOIN [Items] i ON ta.[Item_Id] = i.[Item_Id]
WHERE [IsActive] = 1

繰り返しますが、プロシージャを直接呼び出すときではなく、EF でデッドロックが発生する理由を理解しようとするだけで、うまくいった解決策があります。

ところで、解決策は IsActive ビットを一時テーブルに追加して最初に入力し、次に更新ステートメントの結合で一時テーブル isactive を where 句で使用することでした。

--Create a temp table to hold items based on userid
CREATE TABLE #tableA
(   
    [Id] int identity (1,1),
    [Item_Id] int,
    [IsActive]
)

INSERT INTO #tableA ([Item_Id], [IsActive]) SELECT [Id], [IsActive] FROM [Items] WHERE [UserId] = @UserId

--All of the other processing is omitted for brevity

--Based on final processing above update the IsActive flag on the Items table
UPDATE i
SET [IsActive] = 0
FROM #tableA ta INNER JOIN [Items] i ON ta.[Item_Id] = i.[Item_Id]
WHERE ta.[IsActive] = 1
4

0 に答える 0