I've followed the docs for setting up my many-to-many relationship, using a join table that is exposed as an entity.
But the docs don't mention what I should do about deletion.
So for example, a Student
has many teachers, and a Teacher
has many students. The join entity/table is StudentTeacher
.
The join table/entity:
public class StudentTeacher {
public int StudentId { get; set; }
public Student Student { get; set; }
public int TeacherId { get; set; }
public Teacher Teacher { get; set; }
}
The config for the join table/entity:
modelBuilder.Entity<StudentTeacher>()
.HasOne(b => b.Teacher)
.WithMany(b => b.StudentTeachers)
.HasForeignKey(b => b.TeacherId)
.IsRequired()
.OnDelete(/* ... what goes here? ...*/);
modelBuilder.Entity<StudentTeacher>()
.HasOne(b => b.Student)
.WithMany(b => b.StudentTeachers)
.HasForeignKey(b => b.StudentId)
.IsRequired()
.OnDelete(/* ... what goes here? ...*/);
What do I use in OnDelete()
? And why?
It's seems confusing at first to model the join table, because <=EF6 didn't need it. But it's actually simple.
When deleting a Teacher
entity, you need to delete its relationships to all Student
entities. When deleting a Student
entity, you need to delete its relationships to all Teacher
entities.
So join entities must always be CASCADE
deleted.
.OnDelete(/* ... what goes here? ...*/);
You should specify here what DB must do with child records (in StudentTeacher
) when parent records (in Student
or Teacher
) is deleted: delete too (Cascade
) or prohibit and throw error (Restrict
) if corresponding child record exists. With Restrict
you must manually delete child records before deleting parent one.
But only you can decide what action must be applied for each relationship - this is your application, we don't know all requirements to it.
Important: with Cascade
, deleting, say, Teacher
will affect (delete) only records in StudentTeacher
(with corresponding TeacherId
), but Students
will be keep intact.
Important 2: In MS SQL Server (you didn't wrote what DB engine you are using), you can set only one to Cascade
(other should be Restrict
), or you will receive error when applying migration (Introducing FOREIGN KEY constraint _some_name_ on table _some_table_ may cause cycles or multiple cascade paths.)