2016-03-29 33 views
1

使用EF和C#,我试图做一个具有很多相关记录的实体的克隆。我也想克隆相关记录。顶级对象是Bid实体框架C# - 具有多对多关系的子对象克隆对象

class Bid 
    { 
      Collection<ItemGroup> ItemGroups {get;set;} 
      Collection<Evaluator> Evaluators {get;set;} 
    } 

儿童是ItemGroupsEvaluators。他们是多对多的。

class ItemGroup 
{ 
    Collection<Evaluator> Evaluators {get;set;} 
} 

Class Evaluator 
{ 
    Collection<ItemGroup> ItemGroups {get;set;} 
} 

我克隆Bid,和它的所有孩子,通过与

database.Bids.Add(bid); 
database.SaveChanges(); 

的问题是许多到查询数据库

Bid bid = dbContext.Bids.AsNoTracking().FirstOrDefault() 
        .Include(b => b.ItemGroups) 
        .Include(b => b.ItemGroups.Select(e => e.Evaluators)) 

并添加Bid回 - EvaluatorsItemGroups之间的多种关系。因为他们的集合引用了彼此,所以当您添加Bid时,它会重新记录这些记录。

因此,克隆之前,我有一个出价:

Original Bid - 
Number of ItemGroups = 3 
Number of Evaluators = 2 

,并克隆后,我有新的出价,以:

New Bid - 
Number of ItemGroups = 3 
Number of Evaluators = 6 

这显然是不正确。如何克隆这种关系而不用EF添加重复项?

问题是我的原始查询?我尝试了各种选择,使用.Include()s,从Bid -> Evaluators -> Item Groups跟踪,或者只是去Bid -> EvaluatorBid -> ItemGroup,但没有什么似乎让我很想我想要的。任何和所有的帮助是非常感谢,请让我知道,如果我可以提供一些澄清。提前致谢。

+0

在保存更改之前,您可能有更好的运气来获取启用了跟踪的实体并更改要添加的实体状态。 https://msdn.microsoft.com/en-us/data/jj592676.aspx 我不认为这会导致在你的例子中重复ItemGroups和Elevators,但我没有测试过。 – James

+0

感谢您的意见。我不完全确定这就是我想要去的方式,但当克隆实体更向下时,会导致其他一些意想不到的行为。 – kdeez

回答

0

那么,这是我的超级解决方案,直到有人能告诉我一个更好的方式来做到这一点。基本上,我忽略了我的查询Include()s中的多对多关系,仅查询bid.ItemGroupsbid.Evaluators

我将这些添加为正常,这给我一个Bid与适当数量的项目组和0个评估员,因为ItemGroup - >评估者关系没有建立,因为我没有查询他们。

然后,在调用database.Bids.Add(bid)之后,我重新查询原始出价以及它的Evaluator/ItemGroup关系,并使用名称/ id的/任何可用标识符手动挂接所有Evaluator/ItemGroup引用。

List<Evaluator> originalEvals = db.Bids.Where(b => b.Id == entityId) 
       .Select(b => b.Evaluators) 
       .FirstOrDefault() 
       .ToList(); 
      foreach(Evaluator origEval in originalEvals) 
      { 
       db.Entry(origEval).Reference(e => e.ClientUser).Load(); 
       db.Entry(origEval).Collection(e => e.ItemGroups).Load(); 
      } 

      foreach (Evaluator newEval in bid.Evaluators) 
      { 
       Evaluator originalEval = originalEvals.Where(e => e.ClientUserId == newEval.ClientUserId).FirstOrDefault(); 

       foreach (ItemGroup ig in originalEval.ItemGroups) 
       { 
        newEval.ItemGroups.Add(bid.ItemGroups.Where(g => g.Name == ig.Name).FirstOrDefault()); 
       } 
      } 

低劣,但它的工作原理。