アプリケーションのマルチユーザー環境をシミュレートするために、いくつかのストレス テストを行いたいと考えていました。Entity Framework (EF) を ORM として使用し、バックエンドには SQL Server 2008 R2 Enterprise を使用しています。
モデルの一部を次に示します。すべてのオブジェクト ( NodeBase
) にはMetadatum
オブジェクトがあり、1:1 でマッピングされています。がNodeBase
最初に書き込まれ、次にMetadatum
オブジェクトが 2 番目に書き込まれているようです (または、Metadatum
オブジェクトへの関連付けは不明です)。いずれにせよ、検索を実行するとNodeBase
、 が表示されますが、Metadatum
は null です。5 秒後、同じ検索でMetadatum
オブジェクトが表示されます。:-/. イライラします。
私のテストでは、アプリケーションの 2 つのインスタンスを実行しています (読み取り用の GUI と R/W 用の単体テスト)。単体テストはデータベースに打撃を与え、最悪のシナリオのオブジェクトの読み取りと書き込みを作成し、GUI は発生した DB へのすべての変更を読み取ります (新しいデータの要求で DB に打撃を与えます)。
問題は、私の検索エンジンが、オブジェクトの子と書き込みの前に、新しく書き込まれたオブジェクトを読み込んで処理しているようです。検索で子を処理しようとすると、null 例外が発生します。検索が数秒待った場合 (DateTime.Now.AddSeconds(-5)
うまく機能しているように見えるよりも新しいものはありません)、すべて問題ありません。これは現在の特定の問題では機能しますが、アプリの他の場所では発生しないと思います。
私が試したこと:
私の記述コードでのトランザクション (すべてのオプションが正しいとは限らないか、間違っている可能性があります) が、それは何の効果もないようです。すべての書き込みは、次のトランザクションを使用します。
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = System.Transactions.IsolationLevel.Serializable})) { ContainerResult = OasisModelContainer.SaveChanges(false); OasisModelContainer.AcceptAllChanges(); transactionScope.Complete(); }
最初に別のDBコンテキストで子オブジェクトを先制的にデータベースに書き込もうとしましたが、コンテキストを破棄し、現在のコンテキストで子を再読み取りし、(トランザクションで)親オブジェクトにアタッチしましたが、うまくいきません.
突っついた他のもの、スタックオーバーフローに関するヒントなど。
スナップショットを使用してみましたが、正しく使用できているかどうか確信が持てません - これを自分の DB に設定しました:
ALTER DATABASE [ObjectModel] SET ALLOW_SNAPSHOT_ISOLATION ON ALTER DATABASE [ObjectModel] SET READ_COMMITTED_SNAPSHOT ON
私が考えていること:
書き込み中に設定されたすべてのオブジェクトに WriteLock ブール値を追加し、オブジェクトが読み取られるたびに、WriteLock がクリアされた場合にのみ続行されます。これには大きな意味があり (大量のコードをリファクタリングする)、好ましくありません。
読み取り中のポーリング - 子オブジェクトが Null の場合、遅延して再試行します。繰り返しますが、大規模なリファクタリングの可能性があります。
書き込み中にテーブル/DB ロックを DB に追加します。これが賢明なのか愚かなのかを知るには、SQL Server について十分な知識がありません。デッドロックが発生しないように DB またはテーブルをロックできますか? クライアント アプリがタイムアウトしないように、SQL Server のデッドロック タイムアウトを設定できますか?
ヘルプ/ポインター/アドバイスをいただければ幸いです。