循环引用 Entity Framework 删除教授条目时引用约束失败

Circular Reference Entity Framework Reference Constraint Fails when Deleting Professor Entry

我遇到过不可避免循环引用的情况,我有三个Model 类 : Professor, Module, Element :

我的模型类:

public class Professor{
    public Professor(){
        this.Modules = new HashSet<Module>();
        this.Elements = new HashSet<Element>();
    }
    public int ProfessorID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DayOfBirth { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string PhoneNumber { get; set; }
    public virtual ICollection<Module> Modules { get; set; }
    public virtual ICollection<Element> Elements { get; set; }
}

public class Module {
    public Module() {
        this.ModuleElements = new HashSet<Element>();
    }
    public int ModuleID { get; set; }
    public string Title { get; set; }
    public virtual Professor ResponsibleProfessor { get; set; }
    public int? ProfessorID { get; set; }
    public virtual ICollection<Element> ModuleElements { get; set; }
}

public class Element {
    public int ElementID { get; set; }
    public string Title { get; set; }
    public int? ProfessorID { get; set; }
    public int ModuleID { get; set; }
    public virtual Module Module { get; set; }
    public virtual Professor Professor { get; set; }
}

我的数据库上下文:

public class GI3ASPDOTNETMVCENTITYContext : DbContext {
    public GI3ASPDOTNETMVCENTITYContext() : base("name=GI3ASPDOTNETMVCENTITYContext"){}
    public System.Data.Entity.DbSet<GI3ASPDOTNETMVCENTITY.Models.Student> Students { get; set; }
    public System.Data.Entity.DbSet<GI3ASPDOTNETMVCENTITY.Models.Professor> Professors { get; set; }
    public System.Data.Entity.DbSet<GI3ASPDOTNETMVCENTITY.Models.Module> Modules { get; set; }
    public System.Data.Entity.DbSet<GI3ASPDOTNETMVCENTITY.Models.Element> Elements { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder){
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Module>().HasOptional(m => m.ResponsibleProfessor).WithMany(p => p.Modules).HasForeignKey(m => m.ProfessorID).WillCascadeOnDelete(false);
        modelBuilder.Entity<Element>().HasRequired(e => e.Module).WithMany(m => m.ModuleElements).HasForeignKey(e => e.ModuleID).WillCascadeOnDelete(true);
        modelBuilder.Entity<Element>().HasOptional(e => e.Professor).WithMany(p => p.Elements).HasForeignKey(e => e.ProfessorID).WillCascadeOnDelete(false);
        modelBuilder.Entity<Professor>().HasMany(p => p.Elements).WithOptional(e => e.Professor).WillCascadeOnDelete(false);
        modelBuilder.Entity<Professor>().HasMany(p => p.Modules).WithOptional(m => m.ResponsibleProfessor).WillCascadeOnDelete(false);
    }       
}

我已经在数据库中植入了示例数据,因此在尝试删除教授条目时,它不再说:


The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.Elements_dbo.Professors_ProfessorID". The conflict occurred in database "GI3_1", table "dbo.Elements", column 'ProfessorID'. The statement has been terminated.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.Elements_dbo.Professors_ProfessorID". The conflict occurred in database "GI3_1", table "dbo.Elements", column 'ProfessorID'. The statement has been terminated.

Line 113: Professor professor = db.Professors.Find(id); Line 114: db.Professors.Remove(professor); Line 115:
db.SaveChanges(); Line 116: return RedirectToAction("Index"); Line 117: }

这取决于你希望删除教授后发生什么。在你的情况下,我想它必须从相关的模块和元素中取消分配(而不是删除它们)。

不幸的是,由于您无法打开级联操作,您必须手动执行此操作:

Professor toBeDeleted = ...;
foreach (var module in db.Modules.Where(m => m.ProfessorID == toBeDeleted.ProfessorID))
    module.ProfessorID = null;
foreach (var element in db.Elements.Where(e => e.ProfessorID == toBeDeleted.ProfessorID))
    element.ProfessorID = null;
db.Professors.Remove(toBeDeleted);
db.SaveChanges();