Ответ 1
Когда вы выполняете 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;
, который приведет к обновлению всех свойств/столбцов)
Соответствующая документация: Добавить/Прикрепить и сущности.
Пример кода
Скажем, у вас есть следующее сущность:
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.
Как вы можете видеть, оператор update только обновляет значения, которые были фактически изменены после присоединения объекта к контексту. В зависимости от структуры вашей таблицы это может оказать положительное влияние на производительность.
Теперь, какой вариант лучше для вас, целиком зависит от того, что вы пытаетесь сделать.