Entity Framework Core 5 - 在表上引入 FOREIGN KEY 约束可能会导致循环或多个级联路径

Posted

技术标签:

【中文标题】Entity Framework Core 5 - 在表上引入 FOREIGN KEY 约束可能会导致循环或多个级联路径【英文标题】:Entity Framework Core 5 - Introducing FOREIGN KEY constraint on table may cause cycles or multiple cascade paths 【发布时间】:2021-10-06 13:52:20 【问题描述】:

我正在尝试实现实体框架核心 5 我也是新手。以下是我正在尝试实现的三个模型。

在发布新问题之前,我检查了以下答案,但无法理解卡片示例。也许下面列出的我的问题会帮助今天像我这样的其他人更好地理解它。

    Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why? Foreign key constraint may cause cycles or multiple cascade paths?

我的模型如下:

[Table("Clinics")]
public class Clinic

    public int ClinicID  get; set; 

    public string Name  get; set; 

    public string Description  get; set; 

    public string Address  get; set; 

    public List<Doctor> DoctorsAvailable  get; set;  = new List<Doctor>();



[Table("Doctors")]
public class Doctor

    public int ID  get; set; 

    public string Name  get; set; 

    public DoctorsSpecilization Specilization  get; set; 

    public string PhoneNumber  get; set; 

    public string Email  get; set; 

    public List<Clinic> ClinicsAvailableAt  get; set;  = new List<Clinic>();


 [Table("Patients")]
public class Patient

    public int PatientID  get; set; 

    public string Name  get; set; 

    public string Address  get; set; 

    public string PhoneNumber  get; set; 

    public string Email  get; set; 

    public int DoctorID  get; set; 

    public Doctor Doctor  get; set; 



[Table("Consultations")]
public class Consultation

    public int ID  get; set; 

    public int ClinicID  get; set; 

    public int DoctorID  get; set; 

    public int PatientID  get; set; 

    public Clinic Clinic  get; set; 

    [ForeignKey("DoctorID")]
    public Doctor Doctor  get; set; 

    [ForeignKey("PatientID")]
    public Patient Patient  get; set; 

    public DateTime StartTime  get; set; 

    public DateTime EndTime  get; set; 


问题是咨询模型中医生和患者的导航属性。当我尝试“更新数据库”时它失败了

在表“Consultations”上引入 FOREIGN KEY 约束“FK_Consultations_Patients_PatientID”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 无法创建约束或索引。查看以前的错误。

但是,如果导航属性被删除,它可以正常工作。你可能会问我为什么需要这些导航属性。这是为了在视图上显示相关信息。

非常感谢您对解释或评论该概念的任何帮助。

谢谢。

【问题讨论】:

如果你也显示 Patient 类会很好 所示模型中没有可见的循环。请 (1) 提供第三个相关实体 (Patient) (2) 您是否使用 EF Core 5,因此在 ClinicDoctor 之间存在隐式多对多链接表? @Serge 我已将其添加到代码中。 @IvanStoev 1:添加到代码中。 2:是的 【参考方案1】:

这是所示模型中的级联删除路径

    诊所 -> 咨询 医生->咨询 患者 -> 咨询 医生 -> 病人 -> 咨询

问题(多级联路径)是最后两个。如您所见,删除Doctor时,可以直接删除链接的Consultation记录,也可以查看链接的Patient记录。由于这种可能性,一些数据库(主要是 SqlServer)拒绝级联删除选项,并要求您为形成循环的至少一个关系关闭它并手动或通过触发器处理删除。

所以通常情况下,当这种循环存在时,你应该这样做。

但这里的模型似乎有问题。要么Patient不应该链接到单个Doctor,而是通过链接表和删除Patient.Doctor导航属性(因此关联的FK关系)来链接多个,从而自然打破多个级联路径,即删除Doctor删除只是链接到诊所和病人,而不是诊所和病人本身。

或者,如果您想保持Patient 到单个Doctor 关系,那么Consultation.Doctor(以及关联的Consultation.DoctorId FK 和关系)是多余的 - 可以通过咨询获得咨询的医生。患者。医生)。所以删除它,这也将解决多级联路径问题,因为将不再有Doctor -&gt; Consultation 级联删除链接。

为清楚起见,建议的第一个选项需要更改以下模型:


[Table("Clinics")]
public class Clinic // Unchanged

    public int ClinicID  get; set; 
    public string Name  get; set; 
    public string Description  get; set; 
    public string Address  get; set; 
    public List<Doctor> DoctorsAvailable  get; set;  = new List<Doctor>();


[Table("Doctors")]
public class Doctor

    public int ID  get; set; 
    public string Name  get; set; 
    public string PhoneNumber  get; set; 
    public string Email  get; set; 
    public List<Clinic> ClinicsAvailableAt  get; set;  = new List<Clinic>();
    public ICollection<Patient> Patients  get; set;  // <-- added


[Table("Patients")]
public class Patient

    public int PatientID  get; set; 
    public string Name  get; set; 
    public string Address  get; set; 
    public string PhoneNumber  get; set; 
    public string Email  get; set; 
    //public int DoctorID  get; set;  <-- removed
    //public Doctor Doctor  get; set;  <-- removed
    public ICollection<Doctor> Doctors  get; set;  // <-- added



[Table("Consultations")]
public class Consultation // Unchanged

    public int ID  get; set; 
    public int ClinicID  get; set; 
    public int DoctorID  get; set; 
    public int PatientID  get; set; 
    public Clinic Clinic  get; set; 
    [ForeignKey("DoctorID")]
    public Doctor Doctor  get; set; 
    [ForeignKey("PatientID")]
    public Patient Patient  get; set; 
    public DateTime StartTime  get; set; 
    public DateTime EndTime  get; set; 


和选项 2:


[Table("Clinics")]
public class Clinic // Unchanged

    public int ClinicID  get; set; 
    public string Name  get; set; 
    public string Description  get; set; 
    public string Address  get; set; 
    public List<Doctor> DoctorsAvailable  get; set;  = new List<Doctor>();


[Table("Doctors")]
public class Doctor // Unchanged

    public int ID  get; set; 
    public string Name  get; set; 
    public string PhoneNumber  get; set; 
    public string Email  get; set; 
    public List<Clinic> ClinicsAvailableAt  get; set;  = new List<Clinic>();


[Table("Patients")]
public class Patient // Unchanged

    public int PatientID  get; set; 
    public string Name  get; set; 
    public string Address  get; set; 
    public string PhoneNumber  get; set; 
    public string Email  get; set; 
    public int DoctorID  get; set; 
    public Doctor Doctor  get; set; 



[Table("Consultations")]
public class Consultation

    public int ID  get; set; 
    public int ClinicID  get; set; 
    //public int DoctorID  get; set;  <-- removed
    public int PatientID  get; set; 
    public Clinic Clinic  get; set; 
    //[ForeignKey("DoctorID")]
    //public Doctor Doctor  get; set;  <-- removed
    [ForeignKey("PatientID")]
    public Patient Patient  get; set; 
    public DateTime StartTime  get; set; 
    public DateTime EndTime  get; set; 


【讨论】:

谢谢伊万。在我按照您的建议删除了咨询模型中的医生导航属性和 DoctorID 属性之后。它现在显示错误,因为在表“咨询”上引入外键约束“FK_Consultations_Patients_PatientID”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION。另外,我认为客户是您的回答中的错字,您实际上是指咨询模型? 按照您提到的方式完成了这两件事。它失败。在表“Consultations”上引入 FOREIGN KEY 约束“FK_Consultations_Patients_PatientID”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 尝试从 Consultation 中删除 Doctor 属性,生成迁移,更新数据库,并且它在没有问题的情况下工作。您还有其他未显示的内容吗? 并非如此。同样在这里。删除医生属性后生成迁移,并将 Patient 中的单个医生属性作为医生列表。更新数据库失败。 我唯一做的附加模组是评论public DoctorsSpecilization Specilization get; set; ,因为不知道它是什么。

以上是关于Entity Framework Core 5 - 在表上引入 FOREIGN KEY 约束可能会导致循环或多个级联路径的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 中的日志记录与拦截器

Entity Framework Core中的日志记录与拦截器

Entity Framework Core 中的日志记录与拦截器

Cosmos 的 .NET 5 和 Entity Framework Core (5.0.1) 迁移问题

如何关闭 Entity Framework Core 5 中的所有约定

ASP.NET Core 5 Blazor WASM、gRPC、Entity Framework Core 5:多对多导致堆栈溢出