Entity Framework 6.X 和一对一的关系

Entity Framework 6.X and one-to-one relationship

我有以下型号:

public partial class Driver 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    public virtual AspNetUser AspNetUser { get; set; }
    ......
}


public partial class AspNetUser
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public virtual Driver Driver { get; set; }
    ......
}

和以下映射:

        this.HasOptional(c => c.Driver)
            .WithOptionalPrincipal(a => a.AspNetUser)
            .Map(m => m.MapKey("AspNetUserId"));

它创建了正确的数据库模型,将可为空的 AspNetUserId FK 添加到驱动程序 table。

但是如何在代码中 link 一个对象与另一个对象。我没有 AspNetUserId 属性,所以,我尝试设置对象,如下所示:

        _db.Drivers.Attach(driver);
        _db.AspNetUsers.Attach(aspNetUser);
        driver.AspNetUser = aspNetUser;

        _db.SaveChanges();

但后来我遇到了一个例外:

"An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details."

"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions."

如何用EF解决 6.X ?

Driver 已经与 AspNetUser 相关联时,就会发生这种情况。当您附加 driverAspNetUser 属性 为 null 时,EF 假定 AspNetUserId 的原始值为 null 并生成更新语句 AspNetUserId IS NULL 附加条件,当然与现有记录不匹配,命令 returns 0 条记录受影响,EF 生成相关异常。

解决方法是(1)在设置新值之前从数据库中加载原始Driver.AspNetUser 属性值。此外,为了正确处理新的 AspNetUser 已经与不同的 Driver 相关联的情况,您应该 (2) 加载 AspNetUser.Driver 属性:

_db.Drivers.Attach(driver);
_db.AspNetUsers.Attach(aspNetUser);

_db.Entry(driver).Reference(e => e.AspNetUser).Load(); // (1)
_db.Entry(aspNetUser).Reference(e => e.Driver).Load(); // (2)

driver.AspNetUser = aspNetUser;

_db.SaveChanges();