Entity Framework Attach/Update confusion (EF Core)

Consider the following code:

students entity = new students() {
    Id = 1,
    City = "New York",
    Name = "Sam"
};
using(SomeContext ctx = new SomeContext())
{
    ctx.Entry(entity).State = EntityState.Modified;
    ctx.SaveChanges();
}

Assuming we have a record with id = 1 in the database, the above code will update that entity in the database.

Attach is used when you know that an entity already exists in the database but want to make some changes while change state to modified when you have already made the changes.


In the following example, the entity is obtained by the context, so the context begins tracking it immediately. When you alter property values on a tracked entity, the context changes the EntityState for the entity to Modified and the ChangeTracker records the old property values and the new property values. When SaveChanges is called, an UPDATE statement is generated and executed by the database.

var author = context.Authors.First(a => a.AuthorId == 1);
author.FirstName = "Bill";
context.SaveChanges();

Since the ChangeTracker tracks which properties have been modified, the context will issue a SQL statement that updates only those properties that were changed:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'Bill'

DbContext Update

The DbContext class provides Update and UpdateRange methods for working with individual or multiple entities.

public void Save(Author author)
{
    context.Update(author);
    context.SaveChanges();
}

As with setting the entity's State, this method results in the entity being tracked by the context as Modified. Once again, the context doesn't have any way of identifying which property values have been changed, and will generate SQL to update all properties. Where this method differs from explicitly setting the State property, is in the fact that the context will begin tracking any related entities (such as a collection of books in this example) in the Modified state, resulting in UPDATE statements being generated for each of them. If the related entity doesn't have a key value assigned, it will be marked as Added, and an INSERT statement will be generated.

DBContext Attach

When you use the Attach method on an entity, it's state will be set to Unchanged, which will result in no database commands being generated at all. All other reachable entities with key values defined will also be set to Unchanged. Those without key values will be marked as Added. However, now that the entity is being tracked by the context, you can inform the context which properties were modified so that the correct SQL to update just those values is generated:

var context = new TestContext();
var author = new Author {
    AuthorId = 1,
    FirstName = "William",
    LastName = "Shakespeare"
};
author.Books.Add(new Book {BookId = 1, Title = "Othello" });
context.Attach(author);
context.Entry(author).Property("FirstName").IsModified = true;
context.SaveChanges();

The code above will result in the author entity being marked as Modified, and SQL being generated to update just the FirstName property:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'William'

Reference: Read more