Oleg Sh
Oleg Sh

Reputation: 9013

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

I have the following model:

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; }
    ......
}

and the following mapping:

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

It creates correct DB model, adds nullable AspNetUserId FK to Driver table.

But how to link one object with another in code. I don't have AspNetUserId property, so, I try to set object, like this:

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

        _db.SaveChanges();

but then I got an exception :

"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."

How to solve it with EF 6.X ?

Upvotes: 1

Views: 267

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205729

This is happening when the Driver is already associated with AspNetUser. When you attach the driver with AspNetUser property being null, EF assumes the original value of AspNetUserId being null and generates update statement with AspNetUserId IS NULL additional criteria, which of course does not match the existing record, the command returns 0 records affected and EF generates the exception in question.

The solution is (1) to load the original Driver.AspNetUser property value from the database before setting the new value. Also, in order to correctly handle the case when the new AspNetUser is already associated with a different Driver, you should (2) load AspNetUser.Driver property as well:

_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();

Upvotes: 1

Related Questions