一尘不染

实体框架4-AddObject与Attach

c#

我最近一直在使用Entity Framework
4,对于何时使用ObjectSet.AttachObjectSet.AddObject感到有些困惑。

据我了解:

  • 当系统中已经存在实体时,使用“附加”
  • 创建全新的实体时使用“ AddObject”

因此,如果我要 创建一个新的Person ,则可以执行此操作。

var ctx = new MyEntities();
var newPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.AddObject(newPerson);
ctx.SaveChanges();

如果我要 修改现有的Person ,请执行以下操作:

var ctx = new MyEntities();
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
existingPerson.Name = "Joe Briggs";
ctx.SaveChanges();

请记住,这是一个 非常简单的 示例。实际上,我使用的是Pure
POCO(不生成代码),存储库模式(不处理ctx.Persons)和工作单元(不处理ctx.SaveChanges)。但是,“在幕后”,以上就是我的实现过程。

现在,我的问题 -我还没有找到必须使用 Attach的情况

我在这里想念什么?我们什么时候需要使用Attach?

编辑

只是为了澄清,我正在寻找何时使用AddObject上的Attach的 示例 (反之亦然)。

编辑2

下面的答案是正确的(我接受了),但以为我会添加另一个示例,其中“附加”将很有用。

在我上面的用于 修改现有Person的 示例中,实际上正在执行两个查询。

一个用于检索Person(.SingleOrDefault),另一个用于执行UPDATE(.SaveChanges)。

如果(由于某种原因)我已经知道系统中存在“ Joe Bloggs”,为什么还要进行额外的查询才能首先找到他?我可以这样做:

var ctx = new MyEntities();
var existingPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.Attach(existingPerson);
ctx.SaveChanges();

这将导致仅执行UPDATE语句。


阅读 286

收藏
2020-05-19

共1个答案

一尘不染

ObjectContext.AddObject
ObjectSet.AddObject
ADDOBJECT 方法是将那些新创建的对象 存在于数据库中。该实体将获得自动生成的临时 EntityKey
,其EntityState将设置为 Added 。调用SaveChanges时,对于EF来说很清楚,该实体需要插入数据库中。

ObjectContext.Attach
ObjectSet.Attach

另一方面, Attach 用于数据库中已经 存在的 实体。Attach不会将EntityState设置为Added,而是会产生
Unchanged
EntityState,这意味着自从将它附加到上下文以来,它没有发生变化。假定要附加的对象存在于数据库中。如果在对象附加后对其进行修改,则在调用SaveChanges时,EntityKey的值将用于通过在db表中找到其匹配ID来更新(或删除)相应的行。

此外,使用Attach方法,可以定义ObjectContext中已经存在但具有 没有
自动连接。基本上,Attach的主要目的是连接已附加到ObjectContext且 不是
新实体,因此您不能使用Attach附加已添加EntityState的实体。在这种情况下,您必须使用 Add()

例如,假设您的Person实体具有一个名为 Addresses 的导航属性,它是 Address
实体的集合。假设您已经从上下文中读取了两个对象,但是它们彼此之间不相关,并且您想要这样做:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.PersonReference.Attach(existingPerson)
ctx.SaveChanges();
2020-05-19