C# 删除条目时,循环引用实体框架引用约束失败

C# 删除条目时,循环引用实体框架引用约束失败,c#,sql-server,entity-framework,ef-fluent-api,C#,Sql Server,Entity Framework,Ef Fluent Api,我遇到了一个循环引用不可避免的情况,我有三个模型类:教授、模块、元素: 教授负责零个或多个模块 一个模块有零名或一名教授负责 一个模块可以包含多个元素,也可以不包含任何元素 每个元素由一个或零个前置教师设定 我的模型课: public class Professor{ public Professor(){ this.Modules = new HashSet<Module>(); this.Elements = new HashSet&l

我遇到了一个循环引用不可避免的情况,我有三个模型类:教授、模块、元素:

  • 教授负责零个或多个模块
  • 一个模块有零名或一名教授负责
  • 一个模块可以包含多个元素,也可以不包含任何元素
  • 每个元素由一个或零个前置教师设定
我的模型课:

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; }
}
公共课教授{
公共教授(){
this.Modules=newhashset();
this.Elements=newhashset();
}
公共int教授ID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共DateTime出生日期{get;set;}
公共字符串电子邮件{get;set;}
公共字符串密码{get;set;}
公共字符串PhoneNumber{get;set;}
公共虚拟ICollection模块{get;set;}
公共虚拟ICollection元素{get;set;}
}
公共类模块{
公共模块(){
this.ModuleElements=new HashSet();
}
public int ModuleID{get;set;}
公共字符串标题{get;set;}
公共虚拟教授负责教授{get;set;}
公共int?教授ID{get;set;}
公共虚拟ICollection模块元素{get;set;}
}
公共类元素{
public int ElementID{get;set;}
公共字符串标题{get;set;}
公共int?教授ID{get;set;}
public int ModuleID{get;set;}
公共虚拟模块模块{get;set;}
公共虚拟教授{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);
    }       
}
公共类GI3ASPDOTNETMVCENTITYContext:DbContext{
public GI3ASPDOTNETMVCENTITYContext():base(“name=GI3ASPDOTNETMVCENTITYContext”){}
public System.Data.Entity.DbSet学生{get;set;}
public System.Data.Entity.DbSet{get;set;}
public System.Data.Entity.DbSet模块{get;set;}
public System.Data.Entity.DbSet元素{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder){
基于模型创建(modelBuilder);
modelBuilder.Entity().HasOptional(m=>m.ResponsibleProfessor)。带有许多(p=>p.Modules)。HasForeignKey(m=>m.ProfessorID)。WillCascadeOnDelete(false);
modelBuilder.Entity().HasRequired(e=>e.Module).WithMany(m=>m.ModuleElements).HasForeignKey(e=>e.ModuleID).WillCascadeOnDelete(true);
modelBuilder.Entity().HasOptional(e=>e.Professor)。带有许多(p=>p.Elements)。HasForeignKey(e=>e.ProfessorID)。WillCascadeOnDelete(false);
modelBuilder.Entity().HasMany(p=>p.Elements).WithOptional(e=>e.Professor.WillCascadeOnDelete(false);
modelBuilder.Entity()有许多(p=>p.Modules)。带有可选(m=>m.ResponsibleProfessor)。将级联删除(false);
}       
}

我在数据库中植入了样本数据,因此当试图删除教授条目时,它不再说:


DELETE语句与引用约束“FK_dbo.Elements_dbo.ProfessorID”冲突。冲突发生在数据库“GI3_1”、表“dbo.Elements”、列“ProfessorID”中。 声明已终止

描述:在执行过程中发生未处理的异常 当前的web请求。请查看堆栈跟踪以了解更多信息 有关错误的信息及其在代码中的来源

异常详细信息:System.Data.SqlClient.SqlException:删除 语句与引用约束冲突 “FK_dbo.Elements_dbo.ProfessorID”。冲突发生在 数据库“GI3_1”,表“dbo.Elements”,列“ProfessorID”。这个 声明已终止

第113行:Professor=db.Professors.Find(id); 第114行:db.professor.Remove(professor);第115行:
db.SaveChanges();第116行:返回 重定向操作(“索引”);第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();