【问题标题】:Entity Framework C# - Cloning object with children with many-to-many relationships实体框架 C# - 克隆具有多对多关系的子对象
【发布时间】:2016-07-17 11:30:36
【问题描述】:

使用 EF 和 C#,我正在尝试克隆具有大量相关记录的实体。我也想克隆相关记录。顶级对象是Bid

    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 及其所有子项

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

并用

添加Bid
database.Bids.Add(bid);
database.SaveChanges();

问题在于EvaluatorsItemGroups 之间的多对多关系。因为它们的集合相互引用,所以当您重新添加 Bid 时,它会复制记录。

所以,在克隆之前,我有一个出价:

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

并且,在克隆之后,我有一个新的出价,其中:

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

这显然是不正确的。如何在不让 EF 添加重复项的情况下克隆这种关系?

问题是我原来的查询吗?我已经尝试了各种选择,使用来自Bid -&gt; Evaluators -&gt; Item Groups 的跟踪.Include()s,或者只是去Bid -&gt; EvaluatorBid -&gt; ItemGroup,但似乎没有什么能让我得到我想要的。非常感谢任何和所有帮助,如果我能提供一些澄清,请告诉我。提前致谢。

【问题讨论】:

  • 您可能会更幸运地获取启用了跟踪的实体,而不是在保存更改之前将实体状态更改为添加。 msdn.microsoft.com/en-us/data/jj592676.aspx 我认为这不会导致在您的示例中复制 ItemGroups 和 Elevators,但我没有对此进行测试。
  • 感谢您的意见。我不完全确定这是我想要的方式,但在将实体克隆到图的下方时,它会导致一些其他意外行为。

标签: c# asp.net-mvc entity-framework clone


【解决方案1】:

好吧,这是我的超级笨拙的解决方案,直到有人能告诉我更好的方法。基本上,我在查询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());
                }
            }

糟糕,但它有效。

【讨论】:

    猜你喜欢
    • 2016-05-11
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 2017-01-28
    • 2011-12-17
    相关资源
    最近更新 更多