Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update entities which are modified outside the DbContext?

I've a small problem with updating entities if the entity is changed outside the DbContext (is a detached entity). If I attach the modified entity, it's state is not modified.

My code looks like this:

var specificationToSave = GetSpecificationFromTmpStore(userSessionGuid);
using (var context = DataContextFactory.GetDataContext())
{
    // this works for update, if I change the values inside the context while debugging
    // but it breaks with new entities
    context.Specifications.Attach(specificationToSave);

    // this works for insert new entities, modified entities will be saved as new entities
    context.Specifications.Add((specificationToSave);)
    context.SaveChanges();
}

I know NHibernate and it's method SaveOrUpdate. NHibernate decides because of the values if it is updating or inserting the entities.

What is the best practice to do this with EF 4.x and with entities which are modified outside the DbContext? How can I tell the EF that this entity is in modified state?

like image 945
Juergen Gutsch Avatar asked Sep 06 '12 09:09

Juergen Gutsch


People also ask

How do I update Entity Framework records?

We can update records either in connected or disconnected scenarios. In the connected Scenario, we open the context, query for the entity, edit it, and call the SaveChanges method. In the Disconnected scenario, we already have the entity with use. Hence all we need to is to attach/add it to the context.

How do you update entities?

The steps to update an existing entity are quite simple. First retrieve an instance of the entity from the EntitySet<T> (in our case ObjectSet<Customer>), then edit the properties of the Entity and finally call SaveChanges() on the context.

How does DbContext change state of entity?

This can be achieved in several ways: setting the EntityState for the entity explicitly; using the DbContext. Update method (which is new in EF Core); using the DbContext. Attach method and then "walking the object graph" to set the state of individual properties within the graph explicitly.

Which of the following updates a disconnected entity to the database in EF core?

Entity Framework Core introduced the DbContext. Update() method which attaches the specified entity to a context and sets its EntityState to Modified. Alternatively, you can also use the DbSet. Update() method ( context.


1 Answers

If you use the Attach approach on an entity which has already changed, you will also need to tell EF that the entity is modified, after attaching it.

context.Specifications.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();

An alternative is to fetch (with tracking), then update the fields, and save:

var entity = context.Specifications.First(s => s.Id == 1234);
entity.Name = "Foo";
... other changes here
context.SaveChanges();

Another option is to make the changes to the entity after you have reattached it, e.g. as per here

context.Specifications.Attach(entity);
entity.Name = "Foo";
... other changes here
context.SaveChanges();

Edit

You can use generics with DbSet - either class, or method - as follows:

public void Update<TEntity>(TEntity entity)
{
    DbContext.Set<TEntity>().Attach(entity);
    DbContext.Entry(entity).State = EntityState.Modified;
    DbContext.SaveChanges();
 }

Edit : For updating of detached Parent / Child Graphs

For updating of simple / shallow parent-child relationships where efficiency and performance is not important, simply deleting all old children and reinserting the new ones is an easy (although ugly) solution.

However, for a more efficient scenario requires us to traverse the graph, detect changes, and then add newly inserted, update existing, ignore unchanged, and delete removed items from the Context.

Slauma shows a great example of this here.

You might want to look at using GraphDiff, which can do all this leg work for you!

like image 142
StuartLC Avatar answered Sep 29 '22 04:09

StuartLC