C#Entity Framework 6 - 带有新外键的新记录会创建重复项

时间:2016-04-12 21:04:47

标签: c# entity-framework

我正在使用EF6进行代码优先迁移来创建我的数据库。我的模型犯了一个错误,但我很难理解为什么会发生这种情况。

我有两张桌子

[TrackChanges]
public class Loan
{
    public long Id { get; set; }
    ....
    public virtual LoanAddress LoanAddress { get; set; }

    public Loan() {
        LoanAddress = new LoanAddress();
    }
}

[TrackChanges]
public class LoanAddress
{
    public long Id { get; set; }
    ...
}

当我使用新的LoanAddress创建新的贷款时,它通常会创建两个LoanAddresses。一个被分配给贷款,另一个是孤儿。

    public async Task<IHttpActionResult> Create(LoanViewModel l)
    {
        try
        {
            Loan loan = new Loan
            {
                //LoanAddress = new LoanAddress(),
                ...
            };

            dbContext.Loan.Add(loan);
            await dbContext.SaveChangesAsync(currentUserName);

            return Ok(loan.Id);
        }
        catch (Exception ex)
        {
            ....
        }
    }

如果我调试并逐步执行,dbContext.LoanAddress在Local中有两个条目。

让我感到困惑的是,当

时,这种情况不会发生
  • 数据库为空(它创建一条记录)
  • 有时,当我调试代码并观察LoanAddress时,它可以正常运行
  • 我使用数据库种子方法做类似的事情。它在这里表现得很好

没有帮助的一件事是LoanAddress没有引用贷款。这是一个错误(这对一个没有?),但使用代码优先迁移很难解决它。我在表格中有实时数据,我不确定是否可以解决这个问题。

否则,创建和更新工作,只是创建贷款创建孤立的行。

1 个答案:

答案 0 :(得分:0)

首先,永远不要在实体构造函数中初始化引用导航属性。 Here我已经解释了为什么不。

这有点令人惊讶,这也会导致创建孤立LoanAddress,因为在您的代码中,默认实例(来自构造函数)永远不会附加到更改跟踪器,因为它被替换为添加Loan之前的新实例。当您更新现有的Loan时,可能会发生这种情况。

其次,如果你Add一个实体,属于它的所有实体也被标记为Added(如果它们尚未附加到上下文中)。我假设你实际上打算在这里有一个新的LoanAddress,所以这应该没问题。