Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework - Why explicitly set entity state to modified?

The official documentation says to modify an entity I retrieve a DbEntityEntry object and either work with the property functions or I set its state to modified. It uses the following example

Department dpt = context.Departments.FirstOrDefault(); DbEntityEntry entry = context.Entry(dpt); entry.State = EntityState.Modified; 

I don't understand the purpose of the 2nd and 3rd statement. If I ask the framework for an entity like the 1st statement does and then modify the POCO as in

dpt.Name = "Blah" 

If I then ask EF to SaveChanges(), the entity has a status of MODIFIED (I'm guessing via snapshot tracking, this isn't a proxy) and the changes are persisted without the need to manually set the state. Am I missing something here?

like image 257
SeeNoWeevil Avatar asked Aug 18 '11 10:08

SeeNoWeevil


People also ask

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.

What is EntityState modified?

EntityState.Added : EntityState.Modified; context.SaveChanges(); } } Note that when you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called.

Which of the following method attaches an entity to a context with unchanged entity state?

DbSet.Attach() method attaches an entire entity graph to the new context with the Unchanged entity state.

What is entity state in Entity Framework?

The Entity state represents the state of an entity. An entity is always in any one of the following states. Added: The entity is marked as added. Deleted: The entity is marked as deleted.


2 Answers

In your scenario you indeed don't have to set the state. It is purpose of change tracking to find that you have changed a value on attached entity and put it to modified state. Setting state manually is important in case of detached entities (entities loaded without change tracking or created outside of the current context).

like image 80
Ladislav Mrnka Avatar answered Oct 17 '22 22:10

Ladislav Mrnka


As said, in a scenario with disconnected entities it can be useful to set an entity's state to Modified. It saves a roundtrip to the database if you just attach the disconnected entity, as opposed to fetching the entity from the database and modifying and saving it.

But there can be very good reasons not to set the state to Modified (and I'm sure Ladislav was aware of this, but still I'd like to point them out here).

  1. All fields in the record will be updated, not only the changes. There are many systems in which updates are audited. Updating all fields will either cause large amounts of clutter or require the auditing mechanism to filter out false changes.

  2. Optimistic concurrency. Since all fields are updated, this may cause more conflicts than necessary. If two users update the same records concurrently but not the same fields, there need not be a conflict. But if they always update all fields, the last user will always try to write stale data. This will at best cause an optimistic concurrency exception or in the worst case data loss.

  3. Useless updates. The entity is marked as modified, no matter what. Unchanged entities will also fire an update. This may easily occur if edit windows can be opened to see details and closed by OK.

So it's a fine balance. Reduce roundtrips or reduce redundancy.

Anyway, an alternative to setting the state to Modified is (using DbContext API):

void UpdateDepartment(Department department) {     var dpt = context.Departments.Find(department.Id);     context.Entry(dpt).CurrentValues.SetValues(department);     context.SaveChanges(); } 

CurrentValues.SetValues marks individual properties as Modified.

Or attach a disconnected entity and mark individual properties as Modified manually:

context.Entry(dpt).State = System.Data.Entity.EntityState.Unchanged; context.Entry(dpt).Property(d => d.Name).IsModified = true; 
like image 42
Gert Arnold Avatar answered Oct 17 '22 22:10

Gert Arnold