示例结构
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; }
}
值得注意的是,我的实际结构具有比这更多的级别,但这应该足以解释我想要实现的目标。
所以我加载我的 Page
对象,然后克隆该对象并对 Page
的属性进行一些小的更改,即 Prop1
,Prop2
Page pageFromDb = getPageMethod();
Page clonedPage = pageFromDb.Clone();
clonedPage.Prop1 = clonedPage.Prop1 + " Cloned";
addPageMethod(clonedPage); //Adds the page to db
在上面的示例中,clonedPage
结构很好,一个新的 Page
被添加到数据库中。但是我相信,因为设置了子对象的 ID,并且子对象的关系始终是一对多的。原始对象 pageFromDb
将丢失所有子对象作为 Entity Framework ,而不是为克隆的 Page
创建新的 Section
对象将更新 Section .PageId
到新插入的页面。
我相信解决这个问题的方法是 foreach
、foreach
等,并在插入实体之前将所有 ID 设置为 0
框架将为每个对象创建新记录。有没有更简单/更好的方法来在 Entity Framework 环境中克隆对象?
最佳答案
为了让 Entity Framework 在持久化图时将克隆视为一个全新的对象图,图中的所有实体都需要从检索根实体的上下文中断开。
这可以在上下文中使用 AsNoTracking
方法来完成。
例如,这将从数据库中提取一个页面和相关的部分图表并关闭跟踪。实际上,这是一个克隆,就好像您将其添加到您的页面 DbSet 并保存它将在数据库中创建一个全新的对象图。 IE。一个新的 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
关于c# - Entity Framework 重复对象和所有子属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24828287/