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,因此在 Clinic
和 Doctor
之间存在隐式多对多链接表?
@Serge 我已将其添加到代码中。
@IvanStoev 1:添加到代码中。 2:是的
【参考方案1】:
这是所示模型中的级联删除路径
诊所 -> 咨询 医生->咨询 患者 -> 咨询 医生 -> 病人 -> 咨询
问题(多级联路径)是最后两个。如您所见,删除Doctor
时,可以直接删除链接的Consultation
记录,也可以查看链接的Patient
记录。由于这种可能性,一些数据库(主要是 SqlServer)拒绝级联删除选项,并要求您为形成循环的至少一个关系关闭它并手动或通过触发器处理删除。
所以通常情况下,当这种循环存在时,你应该这样做。
但这里的模型似乎有问题。要么Patient
不应该链接到单个Doctor
,而是通过链接表和删除Patient.Doctor
导航属性(因此关联的FK关系)来链接多个,从而自然打破多个级联路径,即删除Doctor
删除只是链接到诊所和病人,而不是诊所和病人本身。
或者,如果您想保持Patient
到单个Doctor
关系,那么Consultation.Doctor
(以及关联的Consultation.DoctorId
FK 和关系)是多余的 - 可以通过咨询获得咨询的医生。患者。医生)。所以删除它,这也将解决多级联路径问题,因为将不再有Doctor -> 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:多对多导致堆栈溢出