在我的申请中,Agency
有许多Employees
,其中一个被委派给代理机构的所有者:
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public int EmployerId { get; set; }
[ForeignKey("EmployerId")]
public virtual Agency Employer { get; set; }
}
public class Agency
{
public int AgencyId { get; set; }
public string AgencyName { get; set; }
public int OwnerId { get; set; }
[ForeignKey("OwnerId")]
public virtual Employee Owner { get; set; }
[InverseProperty("Employer")]
public virtual ICollection<Employee> Employees { get; set; }
}
我尝试使用以下代码在数据库中输入新的Agency
:
var agency = new Agency();
// ...
context.Agencies.Add(agency);
var owner = new Employee();
// ...
context.Employees.Add(owner);
owner.Employer = agency;
agency.Owner = owner;
context.SaveChanges();
当我调用SaveChanges
时,我收到以下错误,我认为是由于上面描述的循环依赖:
无法确定相关操作的有效排序。 由于外键约束,模型可能存在依赖关系 要求或商店生成的值。
EF中有没有办法指定&#34;依赖操作的顺序&#34;?或者,有没有更好的方法来编写我的数据库,以便解决这个问题,但仍然模拟我想要的数据结构?
答案 0 :(得分:3)
我不确定是否可以在SQL中创建代理商和所有者,因为要向代理商存储您需要有效FK的代理商,并且需要向代理商存储您需要有效FK的所有者。由于FK约束(除非它们不会被强制执行),否则不能在不违反约束的情况下存储任何这些约束。
解决方案(我不知道另一个)正在使其中一个关系成为可选关系,例如Owner
将OwnerId
定义为可空:
public int? OwnerId { get; set; }
这不会立即解决“有效订购”例外情况,但现在您可以存储没有所有者的代理商,然后将所有者与该已存储代理商的关系存储起来。要使整个操作“原子化”,您可以将对SaveChanges
的两个必要调用包装到外部事务中:
using (var tx = new TransactionScope())
{
var agency = new Agency();
context.Agencies.Add(agency);
context.SaveChanges(); // inner transaction 1
// saves agency with OwnerId = NULL, it wouldn't work with a required owner
// agency has a primary key from the database now
var owner = new Employee();
context.Employees.Add(owner);
owner.Employer = agency; // sets FK EmployerId to the now known PK of agency
agency.Owner = owner;
context.SaveChanges(); // inner transaction 2
tx.Complete(); // commits the outer transaction
}