(これは EF 6.4.4 を使用していることに注意してください。)
外部キー プロパティが必要ない限り、指定するのはかなり簡単です。
modelBuilder
.Entity<Order>()
.HasOptional(o => o.Quotation)
.WithOptionalPrincipal(q => q.Order);
modelBuilder
.Entity<Quotation>()
.HasOptional(q => q.Order)
.WithOptionalDependent(o => o.Quotation);
WithOptionalPrincipal
ここで、との両方の使用法に注意してくださいWithOptionalDependent
。これにより、依存側 (例では Quotation) に単一の外部キー列が提供されますが、外部キー プロパティはありません。反対側に外部キーが必要な場合は、「依存」と「プリンシパル」を切り替えます。
(上記の両方の定義を持つ必要はないことに注意してください。WithOptionalDependent
反対側がプリンシパルであり、その逆であることを意味するため、必要に応じて一方のみを使用できますが、両側からの関係を指定するとエラーを防ぐことができます物事を二重に宣言することにより、競合が発生するとモデルエラーが発生し、何かを見逃していることがわかります。)
外部キー列にインデックスがありますが、インデックスには一意の制約がありません。独自の一意の制約 (Key IS NOT NULL
フィルターが必要) を追加することは可能ですが、機能しないようで、関係を更新するときに例外が発生する場合があります。これは、EF が個別のクエリで更新を実行する「スワッピングの問題」に関連していると思われるため、一意性を強制すると、EF は 2 つのステップでキーを「移動」できなくなります。
EF は、一意の DB 制約なしで、関連付け自体を内部的に処理しているようです。
- どちらの側でも、既に使用されている参照を割り当てると、参照の他の使用法が自動的に削除されます。(したがって、コンテキストを開いたときにすでに A1 <=> B1 の場合で、次に A1 => B2 と記述した場合、A1 <=> B1 が削除され、A1 <=> B2 が追加されます。あなたはオンです。)
- 同じ参照を複数回割り当てて重複キーを作成しようとすると、EF は「多重度制約違反」という例外をスローします。(つまり、同じコンテキストで、A1 => B1 と A2 => B1 の両方、または同様の競合するマッピングを記述しました。)
- DB を手動で更新して重複キーの状況を作成する場合、EF がこれに遭遇すると、「リレーションシップの多重性制約違反が発生しました...これは回復不能なエラーです」という例外がスローされます。
EF6 では、プロパティを外部キー列にマップすることはできないようです (少なくとも Fluent API では)。そうしようとすると、プロパティと関連付けの両方に同じ名前を別々に使用しようとするため、一意でない列名の例外が発生します。
また、2 つの外部キー (つまり、両側に 1 つ) を持つことは技術的に正しくないことにも注意してください。このような配置は、実際には0..1 から 0..1 への 2 つの関連付けになります。これは、両端のキーが一致しなければならないということは何もないためです。これは、UI および/または何らかのデータベース制約を介して、別の方法で関係を強制する場合に機能する可能性があります。
また、0..1 から 0..1 への関連付けが正確に何であるかについて、誤解/誤解がある可能性があることにも気付きました。これが意味することは、私の理解と EF の考え方からすると、両側でオプションの 1 対 1 の関連付けであるということです。したがって、関係のない両側にオブジェクトを持つことができます。(1 対 0..1 の関連付けでは、一方のオブジェクトは関係なしに存在できますが、他方のオブジェクトは関連付けるオブジェクトを常に必要とします。)
しかし、0..1 から 0..1 は、関連付けを一方の方向に移動させ、他方の方向には移動させないという意味ではありません。A1 => B1 の場合、B1 => A1 (A1 <=> B1)。A1 を B1 に関連付けずに、B1 を A1 に割り当てることはできません。これが、この関連付けが単一の外部キーのみを使用できる理由です。一部の人々は、これが正しくない関連付けをしようとしている可能性があると思います (A1 は B1 に関連付けられますが、B1 は A1 には関連付けられません)。しかし、それは実際には 1 つの関連付けではなく、2 つの 0..1 から 0..1 への関連付けです。