我理解为什么 EF 在 PK/FK 关系中不允许“循环引用”。我正在寻找有关如何更改我的模型以使以下场景起作用的建议。
设想
三个实体: Employee
、 Agency
、 WorkRecord
。它们的目的是记录员工花在工作上的时间。 Employee
然后包含对他/她受雇的 Agency
的引用,而他/她的 WorkRecord
包含对完成工作的 Agency
的引用。
public class Employee
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int AgencyId { get; set; }
public virtual Agency Agency { get; set; }
public virtual IEnumerable<WorkRecord> WorkRecords { get; set; }
}
public class Agency
{
[Key]
public int Id { get; set; }
}
public class WorkRecord
{
[Key]
public int Id { get; set; }
public int Hours { get; set; }
public int AgencyId { get; set; }
public virtual Agency Agency { get; set; }
public int EmployeeId { get; set; }
public virtual Employee { get; set; }
}
像这样,它婊子:
FK_dbo.WorkRecords_dbo.Employees_EmployeeId
导致循环引用。实验
我的第一个想法是因为双向虚拟属性,所以我决定将两者之一指定为具有单向关系的顶级实体:
首先,我将
WorkRecord
指定为顶级实体,并从 WorkRecords
实体中删除虚拟 Employee
引用引用……产生相同的消息。其次,我将
Employee
设为顶级实体,保留其虚拟 WorkRecords
集合,并从 Employee
实体中删除虚拟 WorkRecord
引用属性...工作正常,但无法实现我的目标。经过更多调查,我发现是两个实体上的 Agency 虚拟引用属性导致了循环引用。如果一个实体将其删除,则
Employee
/WorkRecord
实体关系将在所有方向上起作用。问题:
所以,正如我所问的那样 - 我如何表达这种业务模型,使用
WorkRecord
作为我的顶级实体,而不会让 EF5 感到不安? 最佳答案
听起来您只是想摆脱 EF,但我认为它实际上表达了数据耦合中的一个有效问题。例如,如果您将 AgencyId 绑定(bind)到 WorkRecord 和 Employee,那么更新 WorkRecord 上的 AgencyId 将级联到 Employee。然后将级联到 WorkRecord 等。因此“循环引用”。您确实应该指定哪些数据对象将“拥有”与 Agency 的关系。
就个人而言,我怀疑最自然的绑定(bind)是从 WorkRecord 中引用该机构。我可以看到一个场景,员工可能会从一个机构转移到另一个机构,但 WorkRecord 从一个机构转移到另一个机构要困难得多。还有一种情况是,没有 WorkRecord 的 Employee 不能真正被称为 Employee,真的。如果您确定是这种情况,那么我会从 Employee 中删除 Agency 引用。如果您需要从 Employee 到达代理机构,那么您可能无论如何都应该通过 WorkRecord。
然而,所有这些都只是概念上的。我怀疑,如果您使 Employee 上的 AgencyId 可能为空,EF 将不再提示(并且您可能希望它在两者上都是可选的)。这应该使更新员工有效,而无需使用 WorkRecord 进行循环更新。我必须测试它来验证,但我怀疑它会成立。
public class Employee
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? AgencyId { get; set; }
public virtual Agency Agency { get; set; }
public virtual IEnumerable<WorkRecord> WorkRecords { get; set; }
}