如何在EF Core中进行深度克隆/复制

时间:2018-02-19 20:30:42

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

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

我有以下内容:

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应该足够聪明,可以将该实体添加为新实体。然而,马上就会发生冲突,说'#34; id {schoolId}已经存在"并且不会插入。即使我重置了我想要添加的新项目的ID,我仍然会与学校iteam的关联/子项的ID发生冲突。

是否有人熟悉这一点以及我可能做错了什么?

2 个答案:

答案 0 :(得分:0)

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

Remove certain properties from object upon query EF Core 2.1

答案 1 :(得分:0)

我也遇到了同样的问题,但是在我的情况下,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()

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