zzzprojects / GraphDiff

GraphDiff is a library that allows the automatic update of a detached graph using Entity Framework code first.
https://entityframework-graphdiff.net/overview
MIT License
333 stars 102 forks source link

OwnedEntity fails with Primary Key violation #152

Closed chrismeller closed 6 years ago

chrismeller commented 8 years ago

This is a pretty simple example. Obviously this is a very small subset of our actual model, but assume you have:

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    [ForeignKey("Address")]
    [JsonIgnore]
    public Nullable<int> Address_Id { get; set; }
    public virtual Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

When an update for a Contact comes in, there is no Address_Id foreign key property included. When you attempt to commit you'll get the dreaded Violation of PRIMARY KEY constraint 'PK_dbo.Addresses'. Cannot insert duplicate key in object 'dbo.Addresses'. The duplicate key value is (x). exception.

Stepping through it looks like everything is fine up until ChangeTracker.cs:82, where GraphDiff calls _context.Entry(to).CurrentValues.SetValues(from);. The returned value has null for Address and Address_Id, so when we hit OwnedEntityGraphNode:Update a few steps later it sees dbValue is null and thinks the address is new (hence the insert).

This doesn't seem like a GraphDiff bug per se, but perhaps more of a best practices issue. Should I be using AutoMapper to set explicit FK properties for updates, or should that be handled internally somehow?