何时使用 DbSet<T>.Add() vs DbSet<T>.Attach()?

36

我一直在使用Add(),但遇到了一个问题:当添加子项时,会在数据库中复制父实体。使用Attach()解决了这个问题,但我想知道为什么,而不是盲目地摸索。


我觉得这个链接(https://dev59.com/8m865IYBdhLWcg3wOb9h)有望回答你的问题。 - Conrad Clark
谢谢。这也很有帮助:https://dev59.com/Wm_Xa4cB1Zd3GeqP021p#15310068 - dav_i
2个回答

38

使用Attach方法时,您告诉上下文实体已经存在于数据库中,SaveChanges对已附加的实体没有影响。而Add方法则会更改上下文中实体的状态(如果实体已存在),将其状态更改为Added,这意味着每次调用SaveChanges时都会始终向数据库插入实体。

这就是它们之间的区别。


谢谢回复。那么,为什么在自动生成的“Controller”中,在编辑操作中使用db.Entry(model).State = EntityState.Modified; db.SaveChanges();而不是Attach()呢? - dav_i
2
因为当你Attach()一个已经在上下文中的实体,就像存储在 model 变量中的实体一样,它会将实体的状态设置为 Unchanged,所以如果你为此而使用 Attach(),当你调用 SaveChanges() 时,你的实体将不会被更新。 - Anderson Fortaleza

6

针对ef-core

Attach适用于在数据库中添加带有导航属性的新实体的情况。 Attach仅将新创建的项目标记为更改

假设您要向一个行业添加新员工。如果该行业已存在于数据库中,则必须具有ID。而您要添加的员工尚未插入到数据库中,因此它还没有ID(我在这里谈论行ID)。

因此,attach所做的是:由于行业已经具有ID,因此将其标记为未更改。对于没有ID的员工,attach将其标记为已添加

您可以在此处阅读有关此主题的更多信息:https://www.learnentityframeworkcore.com/dbcontext/modifying-data#attach


2
应该清楚的是,EF6和EF Core在这里是不同的。EF6不会将已附加的实体标记为“Added”。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接