Multiple foreign keys to the same parent table

2019-06-05 16:01发布

问题:

I have the following simplified classes using EF 5 code-first, where my class B has multiple FK's pointing back to class A.

public class A
{
   public int Id {get;set;}
   ICollection<B> Bs {get;set;}
}

public class B
{
   public int Id {get;set;}

   public int A1Id {get;set;}
   public int A2Id {get;set;}
   public int A3Id {get;set;}

   [ForeignKey("A1Id")]
   public A A1 {get;set;}
   [ForeignKey("A2Id")]
   public A A2 {get;set;}
   [ForeignKey("A3Id")]
   public A A3 {get;set;}
}

When I try to build my table I get this error: Introducing FOREIGN KEY constraint 'FK_dbo.B_dbo.A_A1Id' on table 'B' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

I tried modifying the cascade rules through a EntityTypeConfiguration:

        HasOptional(x => x.A1)
            .WithMany()
            .HasForeignKey(p => p.A1Id)
            .WillCascadeOnDelete(false);

Also tried this:

            HasOptional(x => x.A1)
            .WithMany()
            .Map(y => y.MapKey("A1Id"))
            .WillCascadeOnDelete(false);

Following this suggestions: Multiple foreign keys to same primary key table

But still got the same error. All my A1,A2 and A3 FK are optional.

Any ideas on how to get around this error?

Thanks!

回答1:

You have to modify your classes like so:

public class A
{
    public int Id { get; set; }
    public virtual ICollection<B> B1s { get; set; }
    public virtual ICollection<B> B2s { get; set; }
    public virtual ICollection<B> B3s { get; set; }
}

public class B
{
    public int Id { get; set; }
    public int? A1Id { get; set; }
    public int? A2Id { get; set; }
    public int? A3Id { get; set; }

    public virtual A A1 { get; set; }
    public virtual A A2 { get; set; }
    public virtual A A3 { get; set; }
}

Change your Fluent API to this:

modelBuilder.Entity<B>()
.HasOptional(b => b.A1)
.WithMany(a => a.B1s)
.HasForeignKey(k => k.A1Id)
.WillCascadeOnDelete(false);

modelBuilder.Entity<B>()
.HasOptional(b => b.A2)
.WithMany(a => a.B2s)
.HasForeignKey(k => k.A2Id)
.WillCascadeOnDelete(false);

modelBuilder.Entity<B>()
.HasOptional(b => b.A3)
.WithMany(a => a.B3s)
.HasForeignKey(k => k.A3Id)
.WillCascadeOnDelete(false);

This will give you the following table structure: