How to Update Entity by Replacing in EF?

If you want to replace entity with related/child/nested references and collections you can use Tracked Graph since EF Core 2.2. All entities IDs should be database generated.

Add method to your context

public void Replace<TEntity>(TEntity oldEntity, TEntity newEntity) where TEntity : class
{
    ChangeTracker.TrackGraph(oldEntity, e => e.Entry.State = EntityState.Deleted);
    ChangeTracker.TrackGraph(newEntity, e => e.Entry.State = e.Entry.IsKeySet ? EntityState.Modified : EntityState.Added);
}

Usage

var oldOrder = db.Orders
        .AsNoTracking()
        .Include(o => o.Items)
        .Include(o => o.Customer)
        .Find(newOrder.Id);

db.Replace(oldOrder, newOrder);

db.SaveChanges();

Note that old entity should be detatched using AsNoTracking or

db.Entry(oldOrder).State = EntityState.Detached;

I haven't tried this for Entities with Child classes but you could try setting the value.

context.Entry(temp).CurrentValues.SetValues(order);
context.SaveChanges();

This assumes that order is an instance of the Entity Orders. Note this will completely overwrite every property of the temp record with that of order.

This blog has more information (Also applies to EF Core): https://web.archive.org/web/20191225092110/http://kerryritter.com/updating-or-replacing-entities-in-entity-framework-6/


On EF6, there's no built in reliable way to attach a full graph (including related items) on a context (other than Add(), but that doesn't update, just adds). In fact, it's supposed to work (and attach full object graphs), but in practice, it doesn't work and it's very inconsistent, so it's always better to attach every related item yourself.

There are third-party tools like GraphDiff that may help with this task (check its extension method, DbContext.UpdateGraph()), but there is no reliable built-in way.

I'm not sure if EF Core has implemented it already, but it was under discussion (there was this issue going on at GitHub -it's for Add but you'll see Update mentioned throughout the discussion-). It's however closed and I'm not following closely though to know if there are related issues opened)