When you do context.Entry(entity).State = EntityState.Modified;
, you are not only attaching the entity to the DbContext
, you are also marking the whole entity as dirty. This means that when you do context.SaveChanges()
, EF will generate an update statement that will update all the fields of the entity.
This is not always desired.
On the other hand, DbSet.Attach(entity)
attaches the entity to the context without marking it dirty. It is equivalent to doing context.Entry(entity).State = EntityState.Unchanged;
When attaching this way, unless you then proceed to update a property on the entity, the next time you call context.SaveChanges()
, EF will not generate a database update for this entity.
Even if you are planning on making an update to an entity, if the entity has a lot of properties (db columns) but you only want to update a few, you may find it advantageous to do a DbSet.Attach(entity)
, and then only update the few properties that need updating. Doing it this way will generate a more efficient update statement from EF. EF will only update the properties you modified (in contrast to context.Entry(entity).State = EntityState.Modified;
which will cause all properties/columns to be updated)
Relevant documentation: Add/Attach and Entity States.
Code example
Let's say you have the following entity:
public class Person
{
public int Id { get; set; } // primary key
public string FirstName { get; set; }
public string LastName { get; set; }
}
If your code looks like this:
context.Entry(personEntity).State = EntityState.Modified;
context.SaveChanges();
The SQL generated will look something like this:
UPDATE person
SET FirstName = 'whatever first name is',
LastName = 'whatever last name is'
WHERE Id = 123; -- whatever Id is.
Notice how the above update statement will update all the columns, regardless or whether you've actually changed the values or not.
In contrast, if your code uses the "normal" Attach like this:
context.People.Attach(personEntity); // State = Unchanged
personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty.
context.SaveChanges();
Then the generated update statement is different:
UPDATE person
SET FirstName = 'John'
WHERE Id = 123; -- whatever Id is.
As you can see, the update statement only updates the values that were actually changed after you attached the entity to the context. Depending on the structure of your table, this can have a positive performance impact.
Now, which option is better for you depends entirely on what you are trying to do.