实体框架4.3.1的DbContext添加对象与现有引用的对象

问题描述:

(首先抱歉的英语不好)实体框架4.3.1的DbContext添加对象与现有引用的对象

我是新来的实体框架和我做测试的一点点。让我们假设我有2个对象是POCO对象。人员和地址。

我的场景是,我想添加一个新的人到DbContext有一个已经存在的对象的引用。两个实体之间的连接是一个Many:Many关系。

using (var t = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     testaddress = (from c in t.Adresses 
         select c).ToList().FirstOrDefault(); 
} 

var newPerson = new Person(); 
newPerson.Name = "Henry"; 
newPerson.Adresses.Add(testaddress); 

using (var k = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     k.Persons.Add(newPerson); 
     k.SaveChanges(); 
} 

我现在做的问题是,一旦人是增加了一个额外的地址(具有相同的价值观,但一个新的密钥)将被创建。我如何将现有的引用添加到新的对象而不是创建一个新的对象?

+0

最简单的办法是重写的SaveChanges,通过已保存的所有实体和那些(ID> 0),将其设置为“不变”,或者,如果你想坚持最终取得了修改,“修改时间” – UrbanEsc 2012-03-14 17:36:48

整个操作使用一个上下文:

using (var t = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     testaddress = (from c in t.Adresses 
         select c).ToList().FirstOrDefault(); 
     var newPerson = new Person(); 
     newPerson.Name = "Henry"; 
     newPerson.Adresses.Add(testaddress); 
     k.Persons.Add(newPerson); 
     k.SaveChanges(); 
} 

如果你不能做那么,您需要通过ObjectStateManager或类似的方法手动更改新上下文中现有地址的状态。

+0

迭代最后我使用了这些自我追踪对象 – KroaX 2012-03-16 13:19:36

首先,您是否需要在数据上下文的两个单独实例中执行此操作?我假设你这样做,并且你只是提供了一个简化的例子,但是如果没有,那么在整个代码中使用相同的上下文实例将解决你的问题。

但是,这是一个常见问题,特别是在跨WCF等服务使用EF类时。我发现的最佳解决方案是在保存传入的新对象之前“修复”新传入的对象。我会成为第一个管理员,我觉得这个“丑陋”,但我也没有找到任何更好的选项,实际上一直工作。我通常把参考重新关联的代码放到一个方法,在我的实体类的另一部分类段:

public void FixUp(EntityContext c) 
{ 
    for (int i = 0; i < this.Addresses.Count; i++) 
    { 
    var existing = c.Addresses.SingleOrDefault(a => a.Id = this.Addresses[i].Id); 
    if (existing != null) 
    { 
     this.Addresses[i] = existing; 
    } 
    } 
} 

using (var k = new EntityContext()) 
{ 
    newPerson.FixUp(k); 
    k.Persons.Add(newPerson); 
    k.SaveChanges(); 
} 

解释为什么会发生这种情况:您正在创建两个DbContext。首先,您检索一个地址对象。然后,在任何Context范围之外(请参阅使用),您正在创建一个新的脱节人。它不属于你的两种情况之一。接下来发生的事情是,您创建一个新的上下文并添加您的对象到其中。

此背景下,现在不知道你的新(这是“超出范围”,或独立),也不是你的ADRESS(这是从另一个方面)。这两个实体都将被添加并标记为ChangeTracker,已添加

你有多个解决方案:

  • 首先,只能使用一个上下文检索您ADRESS,在创建添加它。你需要稍微改变一下你的代码,如果你正在开发基于服务的场景,它可能不适合你。

  • 第二,如果你有没有改变这个代码的机会,你需要连接分离对象,就像你在你的代码片段做,你可能希望覆盖的SaveChanges你的上下文类,并通过实体迭代在ChangeTracker。那些已保存的(Id> 0)可能会设置为“未更改”,或者如果您想保留最终进行的更改,请使用“修改”。这感觉很难看,但它应该工作。