1

在我的申请中, anAgency有很多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中有没有办法指定“依赖操作”的顺序?或者,是否有更好的方法来编写我的数据库,以便它解决这个问题但仍然模拟我想要的数据结构?

4

1 回答 1

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
}
于 2013-10-13T13:20:07.740 回答