Using both many-to-many and one-to-many to same entity

后端 未结 2 466
野的像风
野的像风 2020-12-18 05:17

I have a many-to-many association in EF Code-First (as explained in this question), and I want to use a one-to-many to the same entity as well. The problem is EF does not pr

相关标签:
2条回答
  • 2020-12-18 05:55

    If table B has foreign key to table A then class B has navigation property to A and A have navigation property to ICollection<A>.
    If table B has many to many relation with table A then class A must have ICollection<B> and class B must have ICollection<A>.

    Try that, maybe this will clarify your request from the EF.

    0 讨论(0)
  • 2020-12-18 06:01

    If you have more than one navigation property refering to the same entity EF does not know where the inverse navigation property on the other entity belongs to. In your example: Does A.ObjectsOfB refer to B.ObjectA or to B.OtherObjectsOfA? Both would be possible and a valid model.

    Now, EF does not throw an exception like "cannot determine relationships unambiguously" or something. Instead it decides that B.ObjectA refers to a third endpoint in B which is not exposed as navigation property in the model. This creates the first foreign key in table B. The two navigation properties in B refer to two endpoints in A which are also not exposed in the model: B.ObjectA creats the second foreign key in table B and B.OtherObjectsOfA creates a foreign key in table A.

    To fix this you must specify the relationships explicitely.

    Option one (the easiest way) is to use the InverseProperty attribute:

    public class A
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [InverseProperty("OtherObjectsOfA")]
        public virtual ICollection<B> ObjectsOfB { get; set; }
    }
    

    This defines that A.ObjectsOfB is part of a many-to-many relation to B.OtherObjectsOfA.

    The other option is to define the relationships completely in Fluent API:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
            .HasMany(a => a.ObjectsOfB)
            .WithMany(b => b.OtherObjectsOfA)
            .Map(x =>
            {
                x.MapLeftKey("AId");
                x.MapRightKey("BId");
                x.ToTable("ABs");
            });
    
        modelBuilder.Entity<B>()
            .HasRequired(b => b.ObjectA)  // or HasOptional
            .WithMany()
            .WillCascadeOnDelete(false);  // not sure if necessary, you can try it
                                          // without if you want cascading delete
    }
    
    0 讨论(0)
提交回复
热议问题