Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
228 views
Welcome To Ask or Share your Answers For Others

1 Answer

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!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...