この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 43712|答える: 4

[出典] 同時タイムスタンプと並行チェックの区別の扱い

[リンクをコピー]
掲載地 2017/04/08 0:10:50 | | | |


著者www.itsvse.com @小渣渣 !
基本データを無事に挿入してください!
ConcurrencyCheck機能のテストは完了しました
アップデート成功! 注1
アップデートは素晴らしいです! 注2、異常情報! 「更新」「挿入/削除」の文を保存すると、予想外の行数(0)に影響が出ました。 エンティティが読み込まれた時点で修正または削除されている可能性があります。 楽的並行例外の理解と取り扱いについては http://go.microsoft.com/fwlink/?LinkId=472540 を参照してください。

タイムスタンプとConcurrencyCheckの違いをテストする
UpdateTab1 アップデート成功! 名前1
UpdateTab2 アップデート成功! 名前1
UpdateTab2のアップデートは異常です! 名前2、異常情報! 「更新」「挿入/削除」の文を保存すると、予想外の行数(0)に影響が出ました。 エンティティが読み込まれた時点で修正または削除されている可能性があります。 楽的並行例外の理解と取り扱いについては http://go.microsoft.com/fwlink/?LinkId=472540 を参照してください。
UpdateTab1 アップデート成功! 名前2

【タイムスタンプ】
TimeStamp機能は、バイト配列プロパティが1つしか持たないフィールドクラスに適用でき、この機能によってtiemStampのタイプがカラムに設定されます。 同時チェックでは、Code-Firstは自動的にこのタイムスタンプタイプのフィールドを使用します。

【同時確認】
ConcurrencyCheck機能はドメインクラスのプロパティに適用可能です。 EFが更新操作を行うと、Code-Firstはその列の値をwhere条件文に入力し、このCurrencyCheck機能を使って既存の列を使って並行性チェックを行うことができ、別々のTimeStamp列を並行性チェックに使う必要はありません。

まずは、並行処理におけるタイムスタンプとConcurrencyCheckの違いを示す新しいコンテキストオブジェクトを作成しましょう!

文脈のためのコードは以下の通りです:




データベースの列を以下のように見てみましょう。



tab1とtab2にはId、Name、Remarkの列があり、tab2はtab1よりもRowVersion列が多いことがわかります。

まずテストコードを添付してください:



【同時処理チェック原理】



Tab1のRemarkプロパティにConcurrencyCheck機能を追加しました。


同じデータのName属性値を同時に更新しても、例外は一切発生しません!


SQL文の生成:


執行sp_executesql N'UPDATE [dbo]。 [タブ1]
SET [名前] = @0
ここで ([Id] = @1) AND ([注記] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name1',@1=1,@2=N'Note1'
執行sp_executesql N'UPDATE [dbo]。 [タブ1]
SET [名前] = @0
ここで ([Id] = @1) AND ([注記] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name2',@1=1,@2=N'note1'

同じデータのRemarkプロパティ値を同時に更新すると、例外を投げます!

SQL文の生成:

執行sp_executesql N'UPDATE [dbo]。 [タブ1]
SET [注記] = @0
ここで ([Id] = @1) AND ([注記] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note1',@1=1,@2=N'Note'
執行sp_executesql N'UPDATE [dbo]。 [タブ1]
SET [注記] = @0
ここで ([Id] = @1) AND ([注記] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note 2',@1=1,@2=N'Note'

同じデータ部分をId 1で同時に取ると、Remark属性の値が得られ、Remark属性を更新する際に更新条件としてRemarkを使います。

最初のSQL文は正常に更新でき、その後注釈が「note 1」に変更され、2つ目のSQL文が更新されると注釈の値が変わったため更新は失敗します。

【タイムスタンプ原理】

Tab2にRowVersionプロパティを追加しました(名前は自由に使えます)し、タイムスタンプ機能も追加しました!!



同じデータのName値を同時に更新すると、最初の更新は成功し、2回目の更新は失敗し、例外が出ます。では、生成されたSQLコードを見てみましょう!

執行sp_executesql N'UPDATE [dbo]。 [タブ2]
SET [名前] = @0
WHERE(([Id] = @1) AND ([RowVersion] = @2)) AND ([注記] = @3))
SELECT [RowVersion]
[DBO]より。 [タブ2]
ここで @@ROWCOUNT > 0 と [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'Name1',@1=1,@2=0x00000000000007D1,@3=N'Note'
執行sp_executesql N'UPDATE [dbo]。 [タブ2]
SET [名前] = @0
WHERE(([Id] = @1) AND ([RowVersion] = @2)) AND ([注記] = @3))
SELECT [RowVersion]
[DBO]より。 [タブ2]
ここで @@ROWCOUNT > 0 AND [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'name2',@1=1,@2=0x00000000000007D1,@3=N'Note'

2つ目のSQL文を実行すると、where条件のデータが見つからないため、更新が失敗し例外がスローされます!!

最初のSQL文が正常に実行されると、RowVersionの値は下図のように変化します。





RowsVersionはタイムスタンプです

アップデートが見逃された際の回避策   

更新不足の概念:ユーザーが同時にデータの行を修正すると、まずデータを読み取り、それをフロントエンドで修正し、修正された後にデータを提出します。これにより、最終的に提出されたデータが以前に送信されたデータを上書きし、更新が失われます。

要するに、アップデートの喪失を防ぐ方法は以下の通りです:

RowsVersionのタイムスタンプを使ってください。

もし行が読み取り前の値と矛盾している場合、それは別のトランザクションがこの列を更新したため、更新できなくなり、更新の損失を防ぐことを意味します。



最後にソースコードを添付します:
CodeFirstDemo.rar (4.94 KB, ダウンロード数: 13)




先の:nhibernate ネイティブの一次キー生成ポリシー
次に:EF6はトランザクション管理にDatabase.BeginTransactionを使用します
掲載地 2022/03/22 11:51:38 |
お疲れさま、とても良い投稿をありがとうございます
 地主| 掲載地 2023/11/01 20:42:15 |
EFの並行性例外 DbUpdateConcurrencyExceptionはキャッシュされた値を再問い合わせします
https://www.itsvse.com/thread-10692-1-1.html
 地主| 掲載地 2023/12/27 19:54:01 |
EF Core 楽観的ロック rowversion 生成の移行文




免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com