实体框架重复对象和所有子属性

Ash*_*way 20 c# entity-framework

示例结构

public class Page
{
    public int PageId { get; set; }
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public virtual List<Section> Sections { get; set; }
}

public class Section
{
    public int SectionId { get; set; }
    public int PageId { get; set; }
    public virtual Page Page { get; set; }
    public virtual List<Heading> Headings { get; set; }
}

public class Heading
{
    public int HeadingId { get; set; }
    public int SectionId { get; set; }
    public virtual Section Section { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

值得注意的是,我的实际结构比这更多,但这应该足以解释我想要实现的目标.

所以我加载我的Page对象然后克隆该对象并对Pageie 的属性进行一些微小的更改Prop1,Prop2

Page pageFromDb = getPageMethod();
Page clonedPage = pageFromDb.Clone();
clonedPage.Prop1 = clonedPage.Prop1 + " Cloned";
addPageMethod(clonedPage); //Adds the page to db
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,clonedPage结构很好,并且Page向数据库添加了new .但是我相信因为孩子们的Id对象被设定了,孩子们的关系总是一对多.原始对象pageFromDb将丢失所有子对象作为实体框架,而不是Section为克隆创建新对象Page将更新Section.PageId到新插入的页面.

我相信,此一解决将是foreach,foreach等,将所有编号的到0,然后插入实体框架将创造新的纪录的foreach对象之前.是否有更简单/更好的方法来克隆实体框架环境中的对象.

Mat*_*ton 35

为了使实体框架在持久化图形时将克隆视为整个新对象图形,图形中的所有实体都需要与检索根实体的上下文断开连接.

这可以使用AsNoTracking上下文中的方法来完成.

例如,这将从数据库中提取页面和关联的部分图形并关闭跟踪.实际上,这是一个克隆,就好像你将它添加到你的Page DbSet并保存它将在数据库中创建一个全新的对象图.即相应的新的Page实体和新的Section实体.请注意,您不需要调用您的Clone方法.

var clone = context.Pages
    .AsNoTracking()
    .Including(pages => pages.Sections)
    .Single(...);
context.Pages.Add(clone);
context.SaveChanges(); // creates an entirely new object graph in the database
Run Code Online (Sandbox Code Playgroud)