Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架复制对象和所有子属性_C#_Entity Framework - Fatal编程技术网

C# 实体框架复制对象和所有子属性

C# 实体框架复制对象和所有子属性,c#,entity-framework,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

示例结构

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; }
}
在上面的例子中,
clonedPage
结构很好,一个新的
Page
被添加到数据库中。但是我相信,因为子对象的Id是设置好的,并且子对象之间的关系总是一对多的。原始对象
pageFromDb
将丢失作为实体框架的所有it子对象,而不是为克隆的
页面创建新的
对象
将更新
节。PageId
到新插入的页面


我认为解决这个问题的方法是
foreach
foreach
,等等。在插入之前,将所有Id设置为
0
,然后实体框架将为每个对象创建新记录。是否有更简单/更好的方法在实体框架环境中克隆对象?

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

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

例如,这将从数据库中提取页面和关联的节图,并关闭跟踪。实际上,这是一个克隆,就好像您将其添加到页面DbSet并保存它将在数据库中创建一个全新的对象图一样。即,新页面实体和相应的新章节实体。注意,您不需要调用
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
试试这个

public Page CopyPage(int pageID)
{
    using(Context context = new Context())
    {
        context.Configuration.LazyLoadingEnabled = false;
        Page dbPage = context.Pages.Where(p => p.PageId == pageID).Include(s => s.Sections.Select(s => s.Section)).First();
        Page page = dbPage.Clone();
        page.PageId = 0;

        for (int i = 0; i < dbPage .Sections.Count; i++)
            page.Sections[i] = new Section
            {
                SectionId = 0,
                PageId = 0,
                Page = null,
                Headings = dbPage[i].Headings
            };
        return page;
    }
}

public Page Clone()
    {
        Object page = this.GetType().InvokeMember("", BindingFlags.CreateInstance, null, this, null);

        foreach(PropertyInfo propertyInfo in this.GetType().GetProperties())
        {
            if(propertyInfo.CanWrite)
            {
                propertyInfo.SetValue(page, propertyInfo.GetValue(this, null), null);
            }
        }

        return page;   
    }
publicpagecopypage(intpageid)
{
使用(上下文=新上下文())
{
context.Configuration.LazyLoadingEnabled=false;
Page dbPage=context.Pages.Where(p=>p.PageId==PageId)。包括(s=>s.Sections.Select(s=>s.Section)).First();
Page=dbPage.Clone();
page.PageId=0;
对于(int i=0;i
克隆方法的作用是什么?它在做深度复制吗?你能告诉它不要复制Id字段吗?只要你的收藏是正确的,EF将在插入后为您建立ID。@Tim仅在顶部
页面
对象级别使用AutoMapper。可能重复
其他信息:检测到对关系“Context.Section\u Page”的角色“Section\u Page\u Target”的冲突更改。
我建议即使没有更改,也要这样做正在跟踪的导航属性仍然被填充。嗯,这很奇怪,因为页面克隆(AsNoTracking)已从上下文中完全删除,因此不能冲突。。。您是否在加载原始页面时只调用了一次上下文,如上所述?除了加载页面和保存克隆之外,还有其他针对您的上下文的工作吗?太棒了,我已经找了很多年了!这种深度克隆是C#的新特性吗?
public Page CopyPage(int pageID)
{
    using(Context context = new Context())
    {
        context.Configuration.LazyLoadingEnabled = false;
        Page dbPage = context.Pages.Where(p => p.PageId == pageID).Include(s => s.Sections.Select(s => s.Section)).First();
        Page page = dbPage.Clone();
        page.PageId = 0;

        for (int i = 0; i < dbPage .Sections.Count; i++)
            page.Sections[i] = new Section
            {
                SectionId = 0,
                PageId = 0,
                Page = null,
                Headings = dbPage[i].Headings
            };
        return page;
    }
}

public Page Clone()
    {
        Object page = this.GetType().InvokeMember("", BindingFlags.CreateInstance, null, this, null);

        foreach(PropertyInfo propertyInfo in this.GetType().GetProperties())
        {
            if(propertyInfo.CanWrite)
            {
                propertyInfo.SetValue(page, propertyInfo.GetValue(this, null), null);
            }
        }

        return page;   
    }