Update与Attach方法的区别及必须使用Update的场景
先明确两者核心区别
Attach是把实体附加到上下文,默认标记为Unchanged状态;Update则是附加后直接标记为Modified状态,SaveChanges时会生成对应更新SQL(可根据配置更新变化字段)。
下面是必须用Update的场景:
处理从上下文外部传入的分离(detached)实体,且需更新属性
比如前端提交的完整Student对象,你没有先从数据库查询获取被跟踪的实体实例。这时候用Update会自动把实体标记为Modified,SaveChanges时会同步属性到数据库。如果用Attach,实体状态是Unchanged,除非手动修改属性并标记为Modified,否则不会生成更新语句。不确定实体是否已被上下文跟踪,需要强制覆盖更新
如果某个实体可能已经在上下文中(比如之前查询过同ID的实体),但你拿到的是另一个实例。用Update会自动处理:上下文会把传入实体的属性值覆盖到已跟踪的实体上,同时标记为Modified;而用Attach的话,会直接抛出InvalidOperationException——因为上下文不能同时跟踪两个同主键的实体。批量更新多个分离实体
当你有一批从外部获取的实体需要更新时,用UpdateRange(Update的批量版本)比逐个Attach再手动标记属性高效得多,它会自动把所有批量传入的实体标记为Modified,大幅减少重复代码。
你给出的示例代码(修正变量名重复问题后):
public void UpdateStudent(Student student) { var dbStudent = _context.Students.FirstOrDefault(s => s.Id == student.Id); dbStudent.FullName = student.FullName; dbStudent.Age = student.Age; _context.Students.Update(dbStudent); // 还是用_context.Students.Attach(dbStudent)? _context.SaveChanges(); }
这里其实既不需要Update也不需要Attach——因为dbStudent是从上下文查询出来的已跟踪实体,修改它的属性后,上下文会自动标记这些属性为Modified,直接调用SaveChanges就能完成更新。如果是直接使用传入的student(没有查询数据库),那才需要用Update,因为它是分离状态的实体。
内容的提问来源于stack exchange,提问作者user22526949

