【问题标题】:How to deep clone/copy in EF Core如何在 EF Core 中进行深度克隆/复制
【发布时间】:2018-07-30 03:12:39
【问题描述】:

我想做的是在 EF Core 中复制/复制我的 School 对象及其所有子/关联

我有类似以下的内容:

var item = await _db.School
.AsNoTracking()
.Include(x => x.Students)
.Include(x => x.Teachers)
.Include(x => x.StudentClasses)
.ThenInclude(x => x.Class)
.FirstOrDefaultAsync(x => x.Id == schoolId);

我一直在阅读有关深度克隆的信息,似乎我应该能够只添加实体...几乎是下一行。

await _db.AddAsync(item);

那么 EF 应该足够聪明,可以将该实体添加为新实体。但是,马上我得到一个冲突,说“id {schoolId} 已经存在”并且不会插入。即使我重置了我要添加的新项目的 ID,我仍然会与学校 iteam 的关联/孩子的 ID 发生冲突。

有没有人熟悉这个以及我可能做错了什么?

【问题讨论】:

  • 从你的item.Id == Guid.NewGuid() 行你没有设置属性,你正在检查是否相等。我假设您实际上并没有在保存之前将属性设置为不同的值。显示更多您正在运行的代码,以便我们提供更好的帮助,但乍一看这似乎是问题所在。
  • 对不起,我想做的只是克隆我的项目对象。我会尝试重新提出我的问题!
  • 实际上这被认为是对 EF Core 2 的改进。即使您调用Add,具有非默认 PK 的实体(例如 0、Guid.Empty 等)也将被视为存在。恐怕“深度克隆”不是 EF Core 目标。见Disconnected Entities
  • 这就是我不希望听到的 :)
  • 你可以用TrackGraph的方法来模拟强制Add。在回调中,您必须将实体 PK 设置为 default(Guid) 并将状态设置为 Added

标签: entity-framework-core deep-copy ef-core-2.0


【解决方案1】:

我也遇到了同样的问题,但在我的情况下,EF 核心抛出异常“id 已经存在”。 按照@Irikos 的回答,我创建了克隆我的对象的方法。

这里是例子

public class Parent
{
    public int Id { get; set; }
    public string SomeProperty { get; set; }
    public virtual List<Child> Templates { get; set; }

    public Parent Clone()
    {
        var output = new Parent() { SomeProperty = SomeProperty };

        CloneTemplates(output);

        return output;
    }

    private void CloneTemplates(Parent parentTo, Child oldTemplate = null, Child newTemplate = null)
    {
        //find old related Child elements
        var templates = Templates.Where(c => c.Template == oldTemplate);

        foreach (var template in templates)
        {
            var newEntity = new Child()
            {
                SomeChildProperty = template.SomeChildProperty,
                Template = newTemplate,
                Parent = parentTo
            };

            //find recursivly all related Child elements
            CloneTemplates(parentTo, template, newEntity);

            parentTo.Templates.Add(newEntity);
        }
    }
}

public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public virtual Parent Parent { get; set; }
    public int? TemplateId { get; set; }
    public virtual Child Template { get; set; }
    public string SomeChildProperty { get; set; }
}

那我就打电话给DbContext.Parents.Add(newEntity)DbContext.SaveChanges()

这对我有用。也许这对某人有用。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,但就我而言,ef core 足够聪明,即使使用现有的 id 也可以将它们保存为新实体。然而,在意识到这一点之前,我只是为所有项目创建了一个复制构造函数,创建了一个仅包含所需属性的本地任务变量并返回了副本。

    Remove certain properties from object upon query EF Core 2.1

    【讨论】:

      猜你喜欢
      • 2017-09-17
      • 1970-01-01
      • 2015-01-08
      • 2012-03-30
      • 2017-11-17
      • 2020-03-04
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多