当你这样做时context.Entry(entity).State = EntityState.Modified;
,您不仅将实体附加到DbContext
,您还将整个实体标记为脏。这意味着当你这样做时context.SaveChanges()
,EF会生成一个更新语句,该语句会更新all实体的字段。
这并不总是理想的。
另一方面,DbSet.Attach(entity)
将实体附加到上下文without将其标记为脏。这相当于做context.Entry(entity).State = EntityState.Unchanged;
以这种方式附加时,除非您继续更新实体上的属性,否则下次调用时context.SaveChanges()
,EF 不会为此实体生成数据库更新。
即使您计划对实体进行更新,如果该实体有很多属性(数据库列)但您只想更新其中几个,您可能会发现执行以下操作是有利的: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.
请注意上面的更新语句将如何更新所有列,无论您是否实际更改了值。
相反,如果您的代码使用“正常”附加,如下所示:
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.
如您所见,更新语句only更新将实体附加到上下文后实际更改的值。根据表的结构,这可能会对性能产生积极的影响。
现在,哪种选择更适合您完全取决于您想要做什么。