3

ASP.NET を使用して、小売企業向けのアプリケーションを構築しています。データ アクセス レイヤーとして Entity Framework (モデル優先) を使用しています。ストアド プロシージャを使用して CRUD 操作を実行していますが、すべての列がマップされており、すべての CRUD 機能が期待どおりに機能しているため、正しいようです。

しかし、DELETE 操作で並行性の問題が発生しています。

TimeStampCRUD操作を行っているテーブルに列を追加しました。UPDATE 操作は、主キーとTimeStamp値によって更新されるため、正常に機能します。したがって、TimeStamp値が変更されたために UPDATE 操作で影響を受ける行がない場合、Entity Framework はOptimisticConcurrencyException.

このDELETE操作は、主キーと値による削除と同じ原理で機能しTimeStampます。TimeStampただし、エンティティとデータベースの間で値が一致しない場合、例外はスローされません。

C# の delete メソッドでは、最初に最新のレコードを取得してから、TimeStampプロパティを別のTimeStamp値に更新します (取得した値とは異なる場合があります)。SQL プロファイラーを使用して調査したところ、DELETEストアド プロシージャが実行されていることがわかりましたが、ストアド プロシージャTimeStampに渡されたパラメーターは最新のTimeStamp値であり、プロパティに設定した値ではありませんTimeStamp。したがって、レコードは削除され、Entity Framework は例外をスローしません。

Entity Framework がTimeStamp、プロパティに割り当てた値ではなく、取得した値を引き続きストアド プロシージャに渡すのはなぜですか? これはデザインですか、それとも何か不足していますか?

どんな助けでも大歓迎です!(あなたが彼女を必要とするとき、ジュリー・ラーマンはどこにいます! :-))

4

2 に答える 2

3

EFの楽観的同時実行性は正常に機能します。ストアドプロシージャでも。

ObjectContext.DeleteObjectsエンティティの元の値を渡して関数を削除します。意味あり。元の値は、削除する行を識別するために使用されます。オブジェクトを削除しても、(通常は)エンティティに意味のある編集はありません。その時、EFは何をすることを期待しますか?書く?どの記録に?

変更されたデータを削除機能に渡すための正当な使用法の1つは、他のテーブル削除を追跡する必要があり、データベース層ではアクセスできない情報をビジネス層でのみスローする必要がある場合です。例には、アプリケーションレベルのユーザー名や削除する理由が含まれます。この状況では、この値を元の値としてエンティティを作成する必要があります。それを行う1つの方法:

var x = db.MyTable.Single(k => k.Id == id_to_delete);
x.UserName = logged_in_user;
x.ReasonForChange = some_reason;
// [...]
db.ObjectStateManager.ChangeObjectState(x, EntityState.Unchanged);
db.MyTable.DeleteObject(x);
db.SaveChanges();

もちろん、より良い戦略は、ビジネスレイヤーでオープンにそれを行うことかもしれません。


rowversion/timestampのユースケースがわかりません。

  1. 同時実行の問題を回避するには、元のタイムスタンプを変更コードに渡します。これにより、データベースの現在の値と比較して、最後に読み取った後にレコードが変更されたかどうかを検出できます。それを新しい値と比較することはほとんど意味がありません。

  2. 通常、SQLServerのrowversion/timestamp、Oracleのrowversion、PostgreSQLのxminなど、データベースによって自動的に更新される変更マーカーを使用します。コード内でその値を変更することはありません。

  3. それでも、行バージョンを手動で保守する場合は、以下を提供する必要があります。

    a)挿入および更新する新しいバージョンを作成し、

    b)同時変更をチェックするために更新および削除する古いバージョン(データベースから読み取る)。

    削除する新しい値を送信しません。あなたはする必要はありません。また、変更にストアドプロシージャを使用する場合は、プロシージャで新しいバージョンを計算してアプリケーションに返すことをお勧めします。その逆ではありません。

于 2013-02-07T14:28:57.270 に答える