2012-03-08 5 views
11

Sections(SQL Server)IDは、ソートの目的で(int, identity)SortIndexの主キーとして使用されます。Entity Frameworkはトリガーによって変更された値を更新しません

データベースには、それぞれINSERTSortIndex := IDを設定するトリガーがあります。明らかに、2つの行の値を入れ替えて後でソートインデックスを変更したいと思います。

私はEntity Frameworkを使用してデータにアクセスします。すべてMVC3 Webアプリケーションでアクセスします。

問題は、テーブルに新しいオブジェクトを挿入した後、Entity FrameworkはSortIndexの値を更新しないということです。また、すべてのデータをキャッシュするので、このテーブルからすべてのオブジェクトを取得する次の呼び出しでも、このオブジェクトの値が誤ってSortIndexになります。

この列のStoreGeneratedPatternEDMXに変更しようとしました。これは素晴らしいとエレガントだが、問題を解決していないようだ。

Identityに設定すると、EFによって値が正しく更新されますが、読み取り専用になります(変更しようとすると例外がスローされます)。 Computedに設定するのは似ていますが、例外がスローされるのではなく、値はDBに書き込まれません。

私はちょうど行うことによって、オブジェクトを挿入した後、それを使用する必要がある場合、私はEFのオブジェクトを毎回再作成することができます。

DatabaseEntities db = new DatabaseEntities() 

をしかし、それは私のために醜い回避策のように思えます。

この問題の解決方法を教えてください。

明らかに、私が毎晩insertの後で何らかのアクションを行う必要がない(忘れられて気づかなかったリスクがある)ことは明らかです。

+0

可能な重複:http://stackoverflow.com/questions/5445243/reload-field-value-in-db-by-after-insert-update –

+0

これは似ていますが、彼は書き込む必要のないフィールドを持っているようです。彼のためには "Computed"がうまくいくはずです。いくつかのバグのせいで動作しません。 – Arek

答えて

15

簡潔に言えば、StoreGeneratedPatternは、値がストアによって処理され、アプリケーションが決して変更しないことを意味します。そのような場合は、SaveChangesに電話をした後に店舗で自動的に値が生成されます。

StoreGeneratedPatternを使用しないと、価値がなくなり、エンティティを更新するために別のクエリを強制的に実行する必要があります。あなたは、たとえば行うことができます:あなたがトリガーとアプリケーションを介して、両方のデータベースの値を更新する必要があり

一般
objectContext.Refresh(RefreshMode.StoreWins, yourSection); 

状況はEF(そしておそらく他のORMツール)と非常にうまく再生されません。

+0

'Refresh'コードをありがとう、それはEFオブジェクトを作り直すよりよく見えます。残念ながら私は評判で投票することはできません。 – Arek

+0

@Arekあなたは答えを受け入れることができます –

+0

私は受け入れることができますが、私はここでいくつかの他の解決策を試しています。 – Arek

0

同じリクエストでその列を再度使用するかどうか知っていますか?

私は新しいEFコンテキストがすべてのリクエストで作成されるので、リクエストごとに1回新しいデータを取得するため、通常は多くの問題を解決します。

長寿命のコンテキストでは、説明したように不整合が増える可能性があります。

とにかく、計算に設定されたStoreGeneratedPatternは正しくなければなりません。しかし、実際のエンティティを格納しているときにのみ更新されます。他のエンティティを挿入または更新することによって更新されていません。あなたは新しいエンティティを作成したり、既存のエンティティを変更する場合は、アプリケーションで使用すると、SaveChangesメソッドを呼び出すときhttp://msdn.microsoft.com/en-us/library/dd296755(v=vs.90).aspx

から

は、計算結果に設定StoreGeneratedPatternとプロパティの値は、サーバーから取得されます。 StoreGeneratedPatternがアプリケーションでComputedに設定されているプロパティに値を割り当てると、SaveChangesメソッドを呼び出すときに値がサーバー生成値で上書きされます。

SQLシーケンシングGUIDの計算値オプションを使用していますが、問題なく動作しています。

+0

私がやっていることは、(1)新しいオブジェクトを追加すること、(2)SortIndexによって注文されたすべてのオブジェクトを取得して返し、Webページを更新することです。だから、同じリクエストでSortIndexを再び使用しています。 – Arek

+0

StoreGeneratedPattert = Computed - これはオブジェクトを正しく更新するようですが、SortIndexはもう修正できません。私は試みますが、私がSaveChanges()を実行すると、古い値が復元されます。 EFはこれらの変更を静かに無視しているようです。 – Arek

+0

はい、storeGeneratedは店舗で生成されていることを明示しているため、書き込むのは面倒ではありません。 おそらく、保存の直後にentity.SortIndex = entity.idを設定するのが最善でしょう。あなたがおそらく望むようにそれを扱うことができます。 –

2

「Ladislav Mrnka」の回答が正確であり、それを受け入れたとマークしました。他の回避策がありますが、いくつかの解決方法を見つけようとしています。しかし、私が探していた解決策は一般的に不可能です。

StoreGeneratedPattern = ComputedをEFに知らせるために、この値が計算される可能性があります。そして、実際にSortIndexの値を変更するストアドプロシージャを作成します。通常、ソート順序を変更するために、2行の値を変更します(スワップします)。このプロシージャは、INSERTのトリガとともに、データがDB内で一貫していることを保証します。 SortIndexに適切な値を設定しないで新しい行を作成することはできません。ストアドプロシージャにバグがない限り、2つのオブジェクトを同じ値にすることはできません。また、編集できないため、手動で値を破棄することはできませんEFを通して。素晴らしい解決策のように見えます。

EFの関数にマップされたストアドプロシージャを簡単に作成することは可能です。

問題は、新しい行を入力しても問題なく、EFはキャッシュ内のデータを正しく更新しますが、ストアドプロシージャを呼び出した後にキャッシュは更新されません。まだいくつかの手動更新またはリフレッシュ機能が必要です。そうでなければ、SortIndexでソートされたgetオブジェクトを呼び出すと、間違った結果が返されます。

それ以外では、いくつかのエンティティにMergeOption = MergeOption.OverwriteChangesを設定することができます。これにより、EFはDBからのデータをいくらか改善します。これが行われると、オブジェクトを挿入した後、またはストアドプロシージャを呼び出した後にオブジェクトを再読み込みすることが可能になり、オブジェクトが更新されます。ただし、db.Section.OrderBy(o => o.SortIndex)でオブジェクトのコレクションを読み取ると、誤った並べ替え順序でキャッシュされた結果が返されます。

誰もが興味を持っている場合、それはEF部分クラスを追加することによって、他の何かにMergeOptionデフォルトにすることが可能だし、ここのような、部分メソッドOnContextCreated、:

public partial class DatabaseEntities 
{ 
    partial void OnContextCreated() 
    { 
     Subsection.MergeOption = MergeOption.OverwriteChanges; 
     Section.MergeOption = MergeOption.OverwriteChanges; 
     Function.MergeOption = MergeOption.OverwriteChanges; 
    } 
} 
+0

ありがとう、それは私のために働く! – Rodrigo

関連する問題