2011-12-07 52 views
3

我想附加一个对象树到我通过WCF服务调用提供的实体框架上下文。有问题的对象具有子项目集合,并且每个子项目都具有属于另一个跟踪对象类型的属性。但是,这些最后的项目只有一小部分,所以大部分收集项目都会共享它们。像这样的事情(除了,很明显,与EntityObjects):实体框架附加()对象树与共享对象

public class Product 
{ 
    public int Id; 
    public string Name; 
    public decimal Cost; 
} 

public class Order 
{ 
    public int Id; 
    public List<Detail> details; 
} 

public class Detail 
{ 
    public int Id; 
    public Product Product; 
    public int Quantity; 
} 

每当我有了同样的产品不止一个详细的订单,实体框架,因为它试图连接的多个拷贝过程中附加抱怨相同的产品密钥。这些信息来自WCF ServiceOperation,因此它将作为Product的离散实例进行反序列化,即使在客户端它们是一组共享对象。

有什么办法可以告诉EF对象上下文重新使用被追踪的实体,当Attach发生时?请注意,我不直接附加产品,所以诸如检查TryGetObjectStateEntry这样的技巧将不起作用。

有什么建议吗?

编辑:

我遇到对自我跟踪实体下面的文章(我已经切换到使用),其中包括一对夫妇可以用来替代Slauma的回答客户端选项跑,这将保留服务器端的协调代码。 (自追踪实体无需使用附加(),但重复键的问题依然存在。)

http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx

回答

1

没有,也没有办法。你基本上需要使每个键的对象引用独特的你连接之前,是这样的:

void PrepareForAttach(Order order) 
{ 
    var dict = new Dictionary<int, Product>(); 
    foreach (var detail in order.Details) 
    { 
     Product firstProduct; 
     if (dict.TryGetValue(detail.Product.Id, out firstProduct)) 
      detail.Product = firstProduct; 
     else 
      dict.Add(detail.Product.Id, detail.Product); 
    } 
} 

EF地图密钥身份对象引用身份,它不允许有两个或多个对象以相同的密钥上下文。它也没有一个功能可以使参考文献具有独特性,这意味着您可以使用与正确产品相同的密钥来选择您的某个产品。 (你可能有两个产品具有相同的密钥但是具有不同的其他属性,那么这个密钥的“正确”产品是什么?EF拒绝决定(如果属性的值都相同,则不会根据属性比较属性),并选择简单和安全的模式:抛出异常。)