3

EF4で親子関係を持つエンティティを保存しようとすると問題が発生しています。子供が親の前に挿入されることもありますが、これは明らかに参照制約の観点から問題を引き起こします。 2つのテーブルは次のように構成されています。外部キーが公開されていないエンティティが不正な順序で保存される

OrderHeader 
- OrderID (PK) 

OrderDetails 
- OrderID (PK) 
- DetailID (PK) 

(これ以上の列はありますが、それは関係ありません)。

メモ: OrderDetails.OrderIDに真の外部キーを公開するのではなく、トリガーを使用してDetailsテーブルのOrderIDがHeaderテーブルに存在するように強制します。 FKを公開するのは簡単な解決策かもしれませんが、私たちのアプリケーションではデータベースへの変更は許されません。つまり、従来のコードなどを扱わなければなりません。

.edmxファイルのXMLデザイナーが生成する、私はそれが概念モデル(CSDLセクション)でAssociationSetとAssociationを作成し、AssociationがReferentialConstraintでセットアップされていることに気づいた。ただし、SSDLセクションにAssociateSetまたはAssocationは作成されません。 FKがデータベースに公開されている場合にのみ追加されるようです。私が(AdventureWorksやNorthwindのような)データベースで真のFKをテストした他のデータベースについては、データベースからモデルを生成すると、EDMXにSSDLのAssociationおよびAssociationSetセクションが含まれていることがわかります。

EFは、モデル(CSDL)にあるアソシエーションを無視して、テーブル名のアルファベット順に挿入するように見えます。このため、OrderDetailはOrderHeaderより前にソートしています(そして、テーブルの名前を変更する権限があります)。対応するアソシエーションセットとアソシエーションをSSDLセクションに手動で追加すると、正しい順序で保存が行われます(最初にヘッダを挿入してからDetailを挿入します)。しかし、「データベースからモデルを更新する」という操作を行うたびに、これらの手動による変更がなくなるため、実際的ではありません。私は実行時にその修正を動的に行うことを考えましたが、「うまくいくはず」を回避するためには多くの努力が必要です。

私は、EFがインサートを注文するときにCSDLで定義されている参照制約および/または関連を尊重する方法があると考えています。

+0

再現性のあるサンプルがありますか?私はこれを何度もやっただけで、(EFv4では)うまくいった。 –

+0

これはFKなしで機能しましたか?それは毎回私のために壊れます。同僚がEFフォーラムの詳細を投稿しました。ここで再現可能なケースを見ることができます:http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/31ffcfa0-e69e-460b-a767-d28376a57fe9大きなことはアソシエーションを持たないようですSSDLセクションのAssociationSetそれがあなたのために働くとき、SSDLセクションに協会がありますか? –

+0

もちろん、特殊なトリガを持たない場合や、SQLをプロファイリングしていない場合、「間違った」動作を見落とすのは簡単です。 FKがなければ、SQL Serverはヘッダーの前に詳細を挿入させる可能性がありますが、それは間違った動作です。 –

答えて

2

Ladislav Mrnkkaの答えを聞いた後、私自身の「簡単な」解決策を見つけることができなかったので、別の解決策を思いつきました。それはいくつかの努力を要しましたが、最終結果は私の意見ではそれに値するものです。

IModelTransofmrationExtension.OnBeforeModelSaved()メソッドを使用するVisual Studio Extensionを作成しました。この方法では、EDMX文書にXDocumentと指定されています。保存する前に、希望どおりに操作できます。この機会を利用して、SSDLに存在しないアソシエーションとアソシエーションセットのCSDLセクションをスキャンします。 Entity/Property名をMSLセクションのデータでTable/Column名にマッピングした後、それらをSSDLセクションにコピーします。

これは効果的にEFをトリックし、私たちの関連に対して実際の外部キーがあると考えて、正しい順序でINSERTを実行します。

唯一の欠点は、モデルを編集するチームの全員が拡張機能をインストールする必要があることです。それ以外の場合、生成されたFKアソシエーションは取得されません。幸いなことに、私たちはモデルを編集する少数の人しかいないので、これは扱いやすいものです。

+0

素晴らしい解決策。 – Alireza

1

実際にFKを使用するように変更するのは、あなたが箱から取り出したいことを確実にすることができないのではない。あなたは、正しい順序で挿入全体を入れてみましたか?そして、保存されたprocにEFが呼び出すprocを呼び出すのであれば、2番目の挿入のIDであればidを取り戻すために出力節を使用しますか?

+0

私たちは手動で(ストアドプロシージャまたはSaveChangesへの複数の呼び出しを介して)挿入物を並べ替えることを考えましたが、このようなテーブルが数多くあり、さらに複雑な関係(親>子>孫)などがあります。本当にそれを避けようとしています。 –

3

私は今問題を理解していると思います。あなたはSSDLには全く関係がありません。 EFがSQLコマンドを生成するとき、それはSSDLからの情報だけを使用するので、CSDLで定義されたエンティティ間の依存性についてはわかりません。私は後でそれを検証しますが、EFアーキテクチャのバグやデザイン上の欠陥のように見えます。

このバグを回避するにはどうすればよいですか? SSDLでアソシエーションセットを手動で定義し、better tool(商用)を使用してEFデザイナーとアップデートマッピングを操作するか、デザイナーがシンプルなシナリオのためだけにEDMXを手動で維持する。

また、Microsoftと提携している場合は、MS Connectにバグとして報告したり、サポートチケットとして追加することもできますが、解決策があっても数ヶ月かかることに注意してください。

+0

情報ありがとうございます。これは、私が恐れていたことを確認します。私たちはSSDLにEFがこれを考慮に入れるための協会が必要です。私はそのツールを見てきましたが、これは有望そうですが、依然として継続的な努力のために努力が必要です。私はこれを行うために私自身のVisual Studioアドインを作ろうと考えています。私たちはそれがどうなるかを見ていきます。追加情報があれば、非常に役に立ちます。 –

+1

でもEF6には同じことがあります... misbehavior :( –