实体框架重复对象和所有子属性 [英] Entity Framework duplicate object and all child properties
问题描述
示例结构
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; }
}
值得注意的是,我的实际结构比这更多,但这应该足以解释我要实现的目标。
It's worth noting that my actual structure has more levels than this but this should be enough to explain what I'm trying to achieve.
因此,我加载了 Page
对象,然后克隆了该对象对象,并对 Page
的属性进行一些小的更改,即 Prop1
, Prop2
So I load my Page
object I then Clone that object and make some minor changes to the properties of Page
i.e. 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
将失去所有作为实体框架的子代,而不是为克隆的<$ c创建新的 Section
对象$ c>页面会将 Section.PageId
更新为新插入的页面。
In the example above clonedPage
structure is fine and a new Page
is added to the database. However I believe because the Id's of the child objects are set and the relationship of the children is always one to many. The original object pageFromDb
will lose all it children as entity framework instead of creating new Section
objects for the cloned Page
will update the Section.PageId
to the newly inserted page.
我相信对此的解决方法是将 foreach
, foreach
等,然后将所有ID设置为 0
在插入之前,实体框架将为每个对象创建新记录。有什么更简单/更好的方法可以在实体框架环境中克隆对象??
I believe a fix for this would be to foreach
, foreach
, etc. and set all the Id's to 0
before inserting then entity framework will create new records foreach object. Is there any easier/better way to clone an object in an entity framework environment.?
推荐答案
以便实体框架能够处理如果将克隆作为一个完整的新对象图保留下来,则该图中的所有实体都必须与检索根实体的上下文断开连接。
In order for Entity Framework to treat the clone as an entire new object graph when persisting the graph, all entities in the graph need to be disconnected from the context in which the root entity was retrieved.
这可以在上下文中使用 AsNoTracking
方法来完成。
This can be done using the AsNoTracking
method on the context.
例如,这将从数据库中提取页面和相关部分的图形并关闭跟踪。实际上,这是一个克隆,就像您将其添加到Page DbSet并将其保存将在数据库中创建一个全新的对象图一样。即新的Page实体和新的Section实体。请注意,您无需调用 Clone
方法。
For example, this will pull a page and associated sections graph from the database and turn off tracking. Effectively this is a clone as if you add this to your Page DbSet and save it will create an entirely new object graph in the database. I.e. a new Page entity and new Section entities accordingly. Note, you wont need to call your Clone
method.
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
这篇关于实体框架重复对象和所有子属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!