Entity Framework Core 5 中多对多关系的 DeleteBehavior

DeleteBehavior on Many-to-Many relationships in Entity Framework Core 5

Entity Framework Core 5 引入了多对多关系,无需直接创建连接表。这很棒,可以加快编码速度,但我遇到了一些挑战。

在处理继承相同 class(人)的两个 classes (student/teacher) 之间的关系时,我在迁移后更新数据库时遇到错误。

Introducing FOREIGN KEY constraint 'FK_Student_TeacherId' on table 'StudentTeacher' 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 or index. See previous errors.

当不使用继承时,多对多关系似乎无法正常工作 class。

public class Person
{
    public int Id { get; set; }
    public string SchoolName { get; set; }
    public int MyProperty { get; set; }
}

public class Teacher : Person
{
    public ICollection<Student> Students { get; set; }
}

public class Student : Person
{
    public ICollection<Teacher> Teachers { get; set; }
}

public class PersonConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.ToTable("Persons").HasKey(k => k.Id);
    }
}

public class TeacherConfiguration : IEntityTypeConfiguration<Teacher>
{
    public void Configure(EntityTypeBuilder<Teacher> builder)
    {
        builder.ToTable("Persons");
        builder.HasMany(p => p.Students).WithMany(t => t.Teachers);
    }
}

public class StudentConfiguration : IEntityTypeConfiguration<Student>
{
    public void Configure(EntityTypeBuilder<Student> builder)
    {
        builder.ToTable("Persons");
    }
}

我可以通过将学生或老师的 onDelete 更改为 ReferentialAction.Restrict

来手动解决问题

但我觉得这个解决方案不好,因为它在联接中留下了孤立行 Table。

显然,根据这个many-to-many-on-delete,EF 没有好的候选者来select 进行限制。所以,你必须在配置时手动定义关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Teacher>()
        .HasMany(t => t.Students)
        .WithMany(s => s.Teachers)
        .UsingEntity<Dictionary<string, object>>(
            "Tutelage",
            j => j.HasOne<Student>().WithMany().OnDelete(DeleteBehavior.Cascade),
            j => j.HasOne<Teacher>().WithMany().OnDelete(DeleteBehavior.Restrict));
}