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

问题描述

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

处理两个继承同一个类(人)的类(学生/教师)之间的关系时,在迁移后更新数据库时出现错误

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.

当不使用继承类时,多对多关系似乎可以无缝地工作。

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

来手动解决该问题

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

解决方法

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

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));
}