web-dev-qa-db-ja.com

このアソシエーションのプリンシパルエンドは、リレーションシップペラティブAPIまたはデータアノテーションを使用して明示的に構成する必要があります

"リレーションシップフルエントAPIまたはデータアノテーションのいずれかを使用して、この関連付けのプリンシパルエンドを明示的に構成する必要があります。"

データベースの更新/移行時にEntity Framework 4.4でこのエラーが発生しますが、1対1の関係を指定しようとはしていません。私はこのようなものが欲しい:

public class EntityA
{
    public int ID { get; set; }
    public int EntityBID { get; set; }

    [ForeignKey("EntityBID")]
    public virtual EntityB EntityB { get; set; }
}

public class EntityB
{
    public int ID { get; set; }
    public Nullable<int> PreferredEntityAID { get; set; }

    [ForeignKey("PreferredEntityAID")]
    public virtual EntityA PreferredEntityA { get; set; }
}

entityAはEntityBの親を持つ必要がありますが、EntityBは優先するEntityAの子を持つことができますが、持つ必要はありません。優先される子は、親に関連付けられている子の1つである必要がありますが、データベースでこれを強制する方法はわかりません。プログラムで強制することを計画しています。

このエラーを回避するにはどうすればよいですか、またはこれらの関係を達成するためのより良い方法は何ですか?

22
lintmouse

Entity Framework Code-Firstの規則では、EntityA.EntityBEntityB.PreferredEntityAが同じ関係に属し、互いに逆のナビゲーションプロパティであると想定しています。ナビゲーションプロパティは両方とも(コレクションではなく)参照であるため、EFは1対1の関係を推測します。

実際には2つの1対多の関係が必要なので、規則をオーバーライドする必要があります。モデルでは、Fluent APIでのみ可能です。

modelBuilder.Entity<EntityA>()
    .HasRequired(a => a.EntityB)
    .WithMany()
    .HasForeignKey(a => a.EntityBID);

modelBuilder.Entity<EntityB>()
    .HasOptional(b => b.PreferredEntityA)
    .WithMany()
    .HasForeignKey(b => b.PreferredEntityAID);

(これを使用する場合、[ForeignKey]属性を削除できます。)

優先される子が常に関連する子の1つであることを保証するマッピングを指定することはできません。

Fluent APIを使用せず、データ注釈のみを使用する場合は、EntityBにコレクションプロパティを追加し、EntityA.EntityB属性を使用して[InverseProperty]に関連付けることができます。

public class EntityB
{
    public int ID { get; set; }
    public Nullable<int> PreferredEntityAID { get; set; }

    [ForeignKey("PreferredEntityAID")]
    public virtual EntityA PreferredEntityA { get; set; }

    [InverseProperty("EntityB")] // <- Navigation property name in EntityA
    public virtual ICollection<EntityA> EntityAs { get; set; }
}
34
Slauma