Удалить каскад с помощью промежуточной таблицы

#c# #entity-framework-core #cascading-deletes

Вопрос:

У меня есть эти сущности Course Student и промежуточная таблица CourseStudent .

 public class Course {  public decimal Id { get; set; }  public decimal IdState { get; set; }  public decimal IdCity { get; set; }  public string Name { get; set; }  public Listlt;CourseStudentgt; CourseStudents { get; set; } = new Listlt;CourseStudentgt;(); }  public class Student {  public decimal Id { get; set; }  public decimal IdState { get; set; }  public decimal IdCity { get; set; }  public string Name { get; set; }  public Listlt;CourseStudentgt; CourseStudents { get; set; } = new Listlt;CourseStudentgt;(); }  public class CourseStudent {  public decimal Id { get; set; }  public decimal IdState { get; set; }  public decimal IdCity { get; set; }  public decimal IdCourse { get; set; }  public decimal IdStudent { get; set; }  public Course Course { get; set; }  public Student Student { get; set; } }  

Мои файлы конфигурации:

 public class CourseStudentConfiguration : IEntityTypeConfigurationlt;CourseStudentgt; {  public void Configure(EntityTypeBuilderlt;CourseStudentgt; builder)  {  builder.ToTable("Courses_Students");  builder.Property(x =gt; x.IdState).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.IdCity).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.IdCourse).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.IdStudent).HasColumnType("numeric(18,0)").IsRequired();   builder  .HasOne(x =gt; x.Course)  .WithMany(x =gt; x.CourseStudents)  .HasForeignKey(x =gt; x.IdCourse)  .OnDelete(DeleteBehavior.Cascade);   builder  .HasOne(x =gt; x.Student)  .WithMany(x =gt; x.CourseStudents)  .HasForeignKey(x =gt; x.IdStudent)  .OnDelete(DeleteBehavior.Cascade);  } }  

Как вы можете видеть, мои отношения находятся только в моей промежуточной таблице.

 public class CourseConfiguration : IEntityTypeConfigurationlt;Coursegt; {  public void Configure(EntityTypeBuilderlt;Coursegt; builder)  {  builder.ToTable("Courses");  builder.Property(x =gt; x.IdState).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.IdCity).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.Name).HasColumnType("varchar(64)").IsRequired();  } }  public class StudentConfiguration : IEntityTypeConfigurationlt;Studentgt; {  public void Configure(EntityTypeBuilderlt;Studentgt; builder)  {  builder.ToTable("Students");  builder.Property(x =gt; x.IdState).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.IdCity).HasColumnType("numeric(18,0)").IsRequired();  builder.Property(x =gt; x.Name).HasColumnType("varchar(64)").IsRequired();  } }  

Когда я удалял некоторые Course CourseStudent , они были удалены, как и ожидалось, но Student они не были удалены, и мне тоже нужно их Student удалить.

Какие изменения мне нужно внести в CourseStudentConfiguration (или StudentConfiguration ), чтобы Student их тоже удалили, когда Course они будут удалены.

Комментарии:

1. Лучший способ-удалить курс, как вы это делаете, а затем удалить студента в отдельном вызове.

Ответ №1:

Задайте себе вопрос, можно ли закодировать его с помощью обычного SQL, потому что, если это невозможно сделать таким образом, его также нельзя настроить в EF.

ON DELETE CASCADE является свойством, установленным для отношения внешнего ключа

 [ CONSTRAINT constraint_name ]  {   FOREIGN KEY   ( column [ ,...n ] )   REFERENCES referenced_table_name [ ( ref_column [ ,...n ] ) ]   [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]   [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]   [ NOT FOR REPLICATION ]  }   

Вы установили два ON DELETE CASCADE для CourseStudent :

  1. IdCourse REFERENCES Courses (Id) ON DELETE CASCADE
  2. IdStudent REFERENECS Students (Id) ON DELETE CASCADE

Это означает, что курс будет удален, если будет удален Студент или Курс. В таблице учащихся не определена связь с внешним ключом, поэтому она не будет удалена — и это ожидаемое поведение. Вы бы также ожидали, что курс будет удален, если студент будет удален? Я так не думаю 🙂

Решение:

  1. Удаляйте объект Student в коде «вручную» каждый раз, когда вы удаляете CourseStudent. Эта логика может быть инкапсулирована в какой-либо репозиторий/сервис.
  2. Вы можете либо определить триггер базы данных

    СОЗДАЙТЕ ТРИГГЕР sampleTrigger В CourseStudent ДЛЯ УДАЛЕНИЯ КАК УДАЛИТЬ ИЗ ученика, В КОТОРОМ УКАЗАН идентификатор (ВЫБЕРИТЕ удалено.IdStudent ИЗ удалено) ПЕРЕЙТИ