2

私はEntity Frameworkで遊んでいましたが、これまではたくさん使っています。しかし、私がこれまで行ってきたことは、ほとんどの場合私にとってうまくいく楽観的なロックを前提としています。しかし、私は次のシナリオを持っている:Entity Frameworkを使用した「次の番号」のシナリオ

  1. アプリケーション全体のデータを保持しているだけで1行
  2. とSQL Serverのテーブルの行は、アプリケーションが番号を読み取る必要がある「NextAvailableNumber」
  3. という名前の列が含まれていますそれを1つ増分して更新する

上記のことは、最初のトランザクションが完了するまで競合するプロセスが番号を取得するのを待たなければならないことを保証する必要があります。以前はテーブルロックを使用していましたが(行が1つしかないため)、LINQ to Entitiesを使用してこれを行う方法を知りたいと思いますか?

おかげで、

ジムK.エンティティ・フレームワークは、楽観的ロックを使用しているので、次の数が第2のプロセスによって変更された場合、それは例外をスローし

答えて

1

これはストアドプロシージャで実装する必要があり、明示的な行ロック(または前述のようにテーブルロック)を使用する必要があると思います。その後、EFからその手続きを呼び出します。特別なテーブルを扱うたびにシリアライズ可能なトランザクションを使用していない限り、アプリケーションコードからこれを処理できるとは思いません。アプリケーションのパフォーマンスに大きな悪影響を与える可能性があります。

私たちは実際には似たようなことをしていますが、テーブルにはさまざまなシーケンスの行がたくさん含まれていますので、行ロックと更新ロックでストアドプロシージャを使用しています。まず、このプロシージャをリポジトリのinsertメソッドでコールしたかったのですが、その後、データベースに移動して、insertトリガからプロシージャを呼び出しました。この理由は、EFコンテキストでの挿入のためにエンティティをマーキングするとき(実際には挿入する必要があり、プロシージャ・コールはこの場合は同じトランザクション内になければなりません)に、データベースへの実際の挿入までの行ロックを無効にするためです。私は関連するプロパティがStoreGeneratedPatternを計算するようにEFモデルを修正しました。各挿入後、EFは、割り当てられたシーケンス番号を取得するためにDBを再クエリーします。唯一の欠点は、EFもこれらのエンティティの各更新後にDBを再クエリしますが、私たちの場合、タイムスタンプのために既にこれを実行していることです。これはまだテストと評価段階にありますので、私はまだ心を変えて再実装することができます。

+0

私は既に利用可能なストアドプロシージャを持っています。これは私が利用できるようなもので、これは私が行かなければならない方法かもしれません。固定要件ではありませんが、自己完結型(コードファースト)でストアドプロシージャを使用しないアプリケーションを作成することが可能かどうかを見たいと思っていました。私はこのシナリオに対処するためにEF内にいくつかの仕組みがあることを期待していました。ありがとう。 –

0

。この状況に対処する最も基本的な方法は、例外をキャッチし、変更が成功するまで変更をやり直すことです。 [最悪のシナリオでコード実行が確実に進むようにタイムアウトを追加できます]

+0

これは私が検討していたものですが、最終的には「気分が悪い」とは限りません。私は、タイマーベースのものを見ているときは、いつも私がやっていることを再考するために一歩前進していることがわかります。これは少量であり、競合の可能性は最小限ですが、EF環境でこのシナリオのベストプラクティスを知りたいと思っています。応答していただきありがとうございます。 –

+0

この場合、現在のところ、カスタムストアドプロシージャを作成し、これを使用して行ロックを実装し、エンティティモデルを介して使用する方法があります。 – manishKungwani

+0

さて、私は@ Ladislav Mrnkaにコメントで言及されたsprocを使用することに辞職していると思う。助けてくれてありがとう。 –

1

私たちが使用している別の解決策があります。特に、私たちのようなEF Code Firstを使用している場合は、ストアプロシージャの使用を避けるために使用できます。コードファーストはストアプロシージャの使用をサポートしていません。

解決策は、トランザクションのスコープ内でEFのSqlQueryメソッドを使用しているため、次の数値カウンタの更新を行うクエリを作成してからItを選択する必要があります。

string query = "UPDATE Registre_Counter SET Counter = Counter + 1 WHERE CounterName = @p0 AND Year = @p1;"; 
query += "select * from Registre_Counter Where CounterName = @p0 AND Year = @p1"; 

GenericCounter GenericCounter = CoreDBContext.Instance().GenericCounter.SqlQuery(query, new Object[] { _counterName, _year }).SingleOrDefault(); //Updates the counter and return de NextNumber to Use 

更新プログラムでは、カウンタがロックされ、トランジションが中止またはコミットされるまでカウンタがロックされ、他のトランザクションからの読み取りは行われません。

関連する問題