2010-03-03 88 views
2

我有一个Visual Studio 2010生成的POCO类集合(刚刚从DB架构生成的POCO模板)。对于给定的用例,我让用户加载一个实体(一个CRM联系人)并采取行动 - 添加电话号码(本身是一个与外键相关的独立实体)和地址(也是一个单独的实体)等。回发我将修改后的实体存储在ViewState中(我不想立即将更改保存到数据库中)。当用户点击保存按钮时会出现问题。主CRM联系人将被保存正常(检测并保存任何更改),但没有任何相关属性会被保存 - 无论是新添加项还是修改后的EF都会忽略它。实体框架中的POCO与快照更改检测

如何强制Entity Framework检测到我的相关属性发生了更改?我使用这个救我的主要联系人:

//contact is an instance of CRMContact retrieved from ViewState 
if (contact.Id == 0) { 
    CRMEntities.CRMContacts.AddObject(contact); 
} else { 
    CRMContact orig = CRMEntities.CRMContacts.Where(c => c.Id == contact.Id).FirstOrDefault(); 
    CRMEntities.CRMContacts.ApplyCurrentValues(contact); 
} 

CRMEntities.SaveChanges(SaveOptions.DetectChangesBeforeSave | SaveOptions.AcceptAllChangesAfterSave); 

也能正常工作联系人实体,但不是我相关的人。我需要添加什么来添加和/或更新电话号码和电子邮件?

请注意,我不想使用基于代理的更改跟踪。

谢谢

回答

2

经过大量的试验和错误,我设法把一些有效的东西放在一起。请注意,我不知道这是否是正确的方式。这是来自项目不同部分的代码。 IAHeader是一个主要实体,IAAttachmentIAComment都通过外键链接到标题:

public static void Save(IAHeader head) { 
    IAHeader orig = new IAHeader(); 
    if (head.Id == 0) { 
     IAData.Entities.IAHeaders.AddObject(head); 
    } else { 
     orig = IAData.Entities.IAHeaders.Where(h => h.Id == head.Id).FirstOrDefault(); 
     IAData.Entities.IAHeaders.ApplyCurrentValues(head); 

     foreach (IAComment comm in head.Comments.ToList()) { 
      if (comm.Id == 0) { 
       comm.IAHeader = null; //disassociate this entity from the parent, otherwise parent will be re-added 
       comm.IAId = head.Id; 
       IAData.Entities.IAComments.AddObject(comm); 
      } else { 
       IAComment origComm = orig.Comments.Where(c => c.Id == comm.Id).First(); 
       IAData.Entities.IAComments.ApplyCurrentValues(comm); 
      } 
     } 

     foreach (IAAttachment att in head.Attachments.ToList()) { 
      if (att.Id == 0) { 
       att.IAHeader = null; //disassociate this entity from the parent, otherwise parent will be re-added 
       att.IAId = head.Id; 
       IAData.Entities.IAAttachments.AddObject(att); 
      } else { 
       IAAttachment origAtt = orig.Attachments.Where(a => a.Id == att.Id).First(); 
       IAData.Entities.IAAttachments.ApplyCurrentValues(att); 
      } 
     } 
    } 
    IAData.Entities.SaveChanges(SaveOptions.DetectChangesBeforeSave | SaveOptions.AcceptAllChangesAfterSave); 
} 

很多可以改进,很明显,但是这是我想出了到目前为止,对我的工作场景。大部分让我困扰的重要部分是不得不将我的导航属性从我的主要实体中解除关联,否则我会得到“实体键已经存在”的错误,或者主实体会被保存两次。

0

我看不到您更改了任何相关值。该docs for ObjectContext.ApplyCurrentValues说:

复制标量值从提供的对象为在ObjectContext的对象具有相同的密钥

(着重号。)

既然你做了没有其他变化,我会说没有什么发现。

+0

我试着循环遍历我的导航属性,并在每个单独的'AddObject'或'ApplyCurrentValues'上执行操作,但是,在这个代码中,我得到了'保存更改时'具有相同键的项目已经被添加'异常,所以我想我的问题是如何正确**在这种情况下创建一个“保存”功能 – 2010-03-03 18:53:32

+0

并且对应用程序各个位置的导航属性进行了更改 - 我发布的内容只是我的“保存”方法的一部分 - 毫无疑问,需要检测的变化 – 2010-03-03 18:56:41

+0

然后,您应该显示该代码。我能看到的只是迄今为止发布的内容;我无法用我从未见过的代码诊断问题。尝试将问题简化为简单的测试用例。 – 2010-03-03 19:37:37