web-dev-qa-db-fra.com

L'extrémité principale de cette association doit être explicitement configurée à l'aide de l'API fluide de la relation ou des annotations de données

"La fin principale de cette association doit être explicitement configurée à l'aide de la relation API fluide ou des annotations de données."

J'obtiens cette erreur dans Entity Framework 4.4 lors de la mise à jour/migration de la base de données, mais je n'essaie pas de spécifier une relation 1: 1. Je veux quelque chose comme ça:

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; }
}

où EntityA doit avoir un parent EntityB, tandis qu'EntityB peut avoir un enfant EntityA préféré, mais ce n'est pas obligatoire. L'enfant préféré devrait être l'un des enfants associés au parent, mais je ne sais pas comment appliquer cela dans la base de données. Je prévois de l'appliquer par programme.

Comment contourner cette erreur ou quelle est la meilleure façon de réaliser ces relations?

22
lintmouse

Les conventions Entity Framework Code-First supposent que EntityA.EntityB et EntityB.PreferredEntityA appartiennent à la même relation et sont les propriétés de navigation inverses les unes des autres. Étant donné que les deux propriétés de navigation sont des références (et non des collections), EF déduit une relation un à un.

Puisque vous voulez réellement deux relations un-à-plusieurs, vous devez remplacer les conventions. Avec votre modèle, cela n'est possible qu'avec l'API Fluent:

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

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

(Si vous l'utilisez, vous pouvez supprimer le [ForeignKey] les attributs.)

Vous ne pouvez pas spécifier un mappage qui garantirait que l'enfant préféré est toujours l'un des enfants associés.

Si vous ne souhaitez pas utiliser l'API Fluent mais uniquement des annotations de données, vous pouvez ajouter une propriété de collection dans EntityB et la lier à EntityA.EntityB en utilisant le [InverseProperty] attribut:

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