I will create two references between Employee and Team entities with foreign keys. So I defined two entities as follow
public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } [ForeignKey("FirstTeam")] public int FirstTeamId { get; set; } [InverseProperty("FirstEmployees")] public virtual Team FirstTeam { get; set; } [ForeignKey("SecondTeam")] public int SecondTeamId { get; set; } [InverseProperty("SecondEmployees")] public virtual Team SecondTeam { get; set; } } public class Team { public int Id { get; set; } public string TeamName { get; set; } [InverseProperty("FirstTeam")] public virtual ICollection<Employee> FirstEmployees { get; set; } [InverseProperty("SecondTeam")] public virtual ICollection<Employee> SecondEmployees { get; set; } }
I thought it is correct theoretically, but it shows the Exception as follow :
{"Introducing FOREIGN KEY constraint 'Employee_SecondTeam' on table 'Employees' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.\r\nCould not create constraint. See previous errors."}
Can anybody help me?
Thanks in advance Kwon
The InverseProperty attribute is used to denote the inverse navigation property of a relationship when the same type takes part in multiple relationships.
The [ForeignKey(name)] attribute can be applied in three ways: [ForeignKey(NavigationPropertyName)] on the foreign key scalar property in the dependent entity. [ForeignKey(ForeignKeyPropertyName)] on the related reference navigation property in the dependent entity.
Inverse Property attribute is used when you need to indicate that navigation property in class A is related to the same foreign key as another navigation property in class B.
To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table.
It is theoretically correct but SQL server (not Entity framework) doesn't like it because your model allows single employee to be a member of both First and Second team. If the Team
is deleted this will cause multiple delete paths to the same Employee
entity.
This cannot be used together with cascade deletes which are used by default in EF code first if you define foreign key as mandatory (not nullable).
If you want to avoid the exception you must use fluent mapping:
public Context : DbContext { public DbSet<Employee> Employees { get; set; } public DbSet<Team> Teams { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Employee>() .HasRequired(e => e.SecondTeam) .WithMany(t => t.SecondEmployees) .HasForeignKey(e => e.FirstTeamId) .WillCascadeOnDelete(false); ... } }
This will result in scenario where you must delete members of SecondTeam manually before you delete the team.
All is correct in previous answer, but one thing is wrong
modelBuilder.Entity<Employee>() .HasRequired(e => e.SecondTeam) .WithMany(t => t.SecondEmployees) .HasForeignKey(e => e.SecondTeamId) // mistake .WillCascadeOnDelete(false);
FirstTeamId
instead of SecondTeamId
will cause that in SecondTeam navigation
property will be always FirstTeam
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With