Когда вы делаете context.Entry(entity).State = EntityState.Modified;
, вы не только присоединяете объект к DbContext
, но также отмечаете всю сущность как грязную. Это означает, что когда вы делаете context.SaveChanges()
, EF сгенерирует оператор обновления, который будет обновлять все поля объекта.
Это не всегда желательно.
С другой стороны, DbSet.Attach(entity)
прикрепляет сущность к контексту без маркировки она грязная. Это эквивалентно выполнению context.Entry(entity).State = EntityState.Unchanged;
При прикреплении этого способа, если вы не приступите к обновлению объекта на объекте, при следующем вызове context.SaveChanges()
EF не будет генерировать обновление базы данных для этого объекта.
Даже если вы планируете сделать обновление для объекта, если у объекта много свойств (столбцы db), но вы хотите обновить несколько, вам может быть полезно сделать DbSet.Attach(entity)
, а затем обновите только несколько свойств, требующих обновления. Выполнение этого способа приведет к созданию более эффективного оператора обновления из EF. EF будет только обновлять измененные вами свойства (в отличие от context.Entry(entity).State = EntityState.Modified;
, что приведет к обновлению всех свойств/столбцов)
Соответствующая документация: Add/Attach and Entity States.
Пример кода
Допустим, у вас есть следующий объект:
public class Person
{
public int Id { get; set; } // primary key
public string FirstName { get; set; }
public string LastName { get; set; }
}
Если ваш код выглядит следующим образом:
context.Entry(personEntity).State = EntityState.Modified;
context.SaveChanges();
SQL, генерироваться будет выглядеть примерно так:
UPDATE person
SET FirstName = 'whatever first name is',
LastName = 'whatever last name is'
WHERE Id = 123; -- whatever Id is.
Обратите внимание, что указанный выше оператор обновления обновит все столбцы независимо от того, действительно ли вы изменили значения или нет.
В противоположность этому, если ваш код использует «нормальный» Attach так:
context.People.Attach(personEntity); // State = Unchanged
personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty.
context.SaveChanges();
Затем сгенерированный оператор обновления отличается:
UPDATE person
SET FirstName = 'John'
WHERE Id = 123; -- whatever Id is.
Как вы можете видеть, оператор обновления только обновляет значения, которые были фактически изменены после присоединения объекта к контексту. В зависимости от структуры вашей таблицы это может оказать положительное влияние на производительность.
Теперь, какой вариант лучше для вас, целиком зависит от того, что вы пытаетесь сделать.
Лучше добавьте некоторую информацию о версии, об этом просили раньше. Я не понимаю, заслуживает ли этого вопроса новый вопрос. –