6

オプティミスティック コンカレンシーを処理するために rowversion 列を使用しており、更新を行ったときに新しい rowversion 値を取得して、データ レイヤーに最新の値が含まれるようにし、コンカレンシー例外を取得して別の更新を実行できるようにしたいと考えています (レコードが他の人によって更新されています)。

更新を行った後、データレイヤーで取得を行っていましたが、これはあまり効率的ではなく、完全に信頼できるものでもありませんでした。

次の表の場合:

CREATE TABLE PurchaseType
(
    PurchaseTypeCode nvarchar(20) NOT NULL PRIMARY KEY CLUSTERED (PurchaseTypeCode),
    Name nvarchar(50) NOT NULL,
    TS rowversion NOT NULL
)

私は試した:

CREATE PROCEDURE PurchaseType_UpdateWithGet
@PurchaseTypeCode nvarchar(20),
@Name nvarchar(50),
@TS rowversion OUTPUT    
AS

UPDATE PurchaseType
SET Name = @Name
WHERE PurchaseTypeCode = @PurchaseTypeCode
 AND TS = @TS

SELECT @TS = TS FROM PurchaseType WHERE PurchaseTypeCode = @PurchaseTypeCode
GO

しかし、他の誰かの更新から rowverion の値を取得できない可能性があるため、完全には満足していませんでした。次に、rowversion のドキュメント (http://msdn.microsoft.com/en-us/library/ms182776.aspx / http://msdn.microsoft.com/en-us/library/ms177564.aspx ) で OUTPUT ステートメントに出くわしました。 )そしてこれを試しました:

CREATE PROCEDURE PurchaseType_UpdateWithOutput
@PurchaseTypeCode nvarchar(20),
@Name nvarchar(50),
@TS rowversion OUTPUT    
AS

DECLARE @Output TABLE (TS BINARY(8))

UPDATE PurchaseType
SET Name = @Name
    OUTPUT inserted.TS into @Output
WHERE PurchaseTypeCode = @PurchaseTypeCode
    AND TS = @TS

SELECT TOP 1 @TS = TS FROM @Output
GO

これはうまくいきます。私の非常に基本的なテスト (10000 回の呼び出しを実行してタイミングを取るだけ) では、OUTPUT オプションは約 40% 長くかかりますが、それでも 0.5 ミリ秒未満です。どちらもSET STATISTICS TIME ONで測定可能な時間はかかりませんでした.

私の質問は、これを行うためのより良い/より簡単な方法を知っている人はいますか?

ID 列に SCOPE_IDENTITY() に似た関数を使用できることを期待していましたが、そのようなものは見つかりませんでした。私が何かを見逃しているかどうか誰にも分かりますか?

前もって感謝します。

4

2 に答える 2

1

MSDNから:

@@DBTS は、現在のデータベースの最後に使用されたタイムスタンプ値を返します。タイムスタンプ列を持つ行が挿入または更新されると、新しいタイムスタンプ値が生成されます。

于 2013-10-23T15:04:00.557 に答える
0

あなたの問題は、更新と選択の間に他の誰かが行を更新することです。したがって、更新ステートメントの後に選択すると、同じ値が得られません。これは、反復不可能な読み取りの問題です。update ステートメントでは、ロッキング ヒント (UPDLOCK) を使用する必要があります。このロックはリーダー (共有ロック) を許可しますが、ライターはブロックします。したがって、更新後に同じ行が取得されます。したがって、ストアドプロシージャは-

CREATE PROCEDURE PurchaseType_UpdateWithGet
@PurchaseTypeCode nvarchar(20),
@Name nvarchar(50),
@TS rowversion OUTPUT    
AS

UPDATE PurchaseType with (updlock)
SET Name = @Name
WHERE PurchaseTypeCode = @PurchaseTypeCode
 AND TS = @TS

SELECT @TS = TS FROM PurchaseType WHERE PurchaseTypeCode = @PurchaseTypeCode
GO
于 2016-01-27T18:45:25.760 に答える