实体框架4 - AddObject与附件

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (30)

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

从我的理解:

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

所以,如果我创建一个新的人,我这样做。

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

如果我修改现有的人,我这样做:

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

请记住,这是一个非常简单的例子。实际上,我使用的是Pure POCO(无代码生成),Repository模式(不处理ctx.Persons)和Unit of Work(不处理ctx.SaveChanges)。但是“在封面下”,以上是我执行过程中发生的情况。

现在,我的问题 - 我还没有找到一个场景,我不得不使用附加

我在这里错过了什么?我们什么时候需要使用Attach?

为了澄清,我正在寻找什么时候使用Add over AddObject的例子(反之亦然)。

在我上面修改现有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语句。

提问于
用户回答回答于

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

ObjectContext.Attach ObjectSet.Attach: 另一方面, Attach用于数据库中已存在的实体。将结果添加到未更改的 EntityState中,而不是将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();
用户回答回答于

这是一个迟到的反应,但它可能会帮助其他人发现这一点。

基本上,当您操作“使用”范围之外的实体时,可能会发生“断开连接”的实体。

Employee e = null;

using (var ctx = new MyModelContainer())
{
     e = ctx.Employees.SingleOrDefault(emp => emp .....);
}

using (var ctx2 = new MyModelContainer())
{
     e; // This entity instance is disconnected from ctx2
}

如果你输入另一个“使用”范围,那么“e”变量将被断开,因为它属于前一个“使用”范围,并且由于先前的“使用”范围被销毁,所以“e”被断开。

扫码关注云+社区