1対多の関係は、関係の最初の端に1つの要素があり、もう一方の端に多くの要素があるため、1対多と呼ばれます。また、 0または1対多の関係を持つこともできます。これは、非多側の要素がnull
(またはNULL
データベース内で)存在できることを意味するだけです。
定義しようとしているのは、2対多(またはおそらく0または1または2対多)の関係です。そのようなものは、リレーショナルデータベースには存在せず、EntityFrameworkにも存在しません。
EFとの関係を定義するときは、ソースクラスとターゲットクラスに2つのナビゲーションプロパティのペアが常に必要です。ナビゲーションプロパティの1つを省略することは可能ですが、それは、この関係の終わりを、すでに別の関係に属している別のナビゲーションプロパティに移動できることを意味するものではありません。
特定のケースでは、2つのナビゲーションプロパティFirstEnd
とSecondEnd
がShaft
2つの異なる外部キーを表すため、2つの関係があります。したがって、に2つのコレクションが必要であるCoupling
か、既存のプロパティCoupling.Shafts
をどちらか一方にFirstEnd
関連付けることができますSecondEnd
が、両方に関連付けることはできません。もう1つの参照は、の「非表示」で公開されていないナビゲーションコレクションを指しCoupling
ます。(これは、あなた自身の答えのマッピングで起こることです。EFは、最初のマッピングブロックを上書きする2番目のマッピングブロックを取得し、との間の関係を作成しSecondEnd
、次に、公開されていない関係とShafts
の間の別の関係を作成します。FirstEnd
Coupling
Shafts
2つのコレクションを使用したソリューション(私の意見ではより理にかなっています)は、次のようになります。
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
}
そしてこのマッピング:
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithFirstEndHere)
.WithOptional(x => x.FirstEnd);
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithSecondEndHere)
.WithOptional(x => x.SecondEnd);
読み取り専用でマップされていないヘルパープロパティを作成して、2つのコレクションを1つのコレクションに連結できますが、この連結は、2つのナビゲーションコレクションが既に読み込まれた後にメモリ内で行われます。
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
// not mapped to DB because it has only a getter = readonly
public IEnumerable<Shaft> Shafts
{
get { return ShaftsWithFirstEndHere.Concat(ShaftsWithSecondEndHere); }
}
}
このような連結を自動的に行うようなマッピングはありません。1対多の関係にあるナビゲーションコレクションプロパティは、依存テーブル(Shaft
例では=)の外部キーによるクエリの結果であることに注意してください。コレクションにデータを入力するために使用される外部キー(Include
たとえば、遅延読み込みがトリガーされた場合など)は、リレーションシップマッピングによって明確に定義され、キーFirstEnd
またはキーのいずれかであり、SecondEnd
両方ではありません。達成しようとしているのは、2つの異なる外部キーによる2つのクエリの連結結果です。そして、それはリレーションシップマッピングでは不可能です。