如何在EF Core中更新1个子级来添加父级和2个子级实体?

时间:2019-05-19 16:10:36

标签: entity-framework entity-framework-core

我有一个具有Child1列表的父实体。 Child1实体具有Child2实体列表。 我的目标是在datyabase上创建Parent和2级child(Child2)实体,并更新Child1实体上的parentId。让我提供详细信息。

Parent{

int ID;
List<Child1> child1;
.....
}

Child1{
int ID;
int parent_ID;
....
List<Child2> child2;

}

Child2{
int ID;
int child1_ID;

....

}

如何通过EF Core实现此操作?

1 个答案:

答案 0 :(得分:0)

您可能需要澄清打算发生的事情:

例如,根据您的描述,如果您拥有当前信息:

Parent: "Dad"
  Child1s (1)
  -> Child1: "Peter"
     Child2s (0)

您要添加一个新的“父母”“妈妈”,将“彼得”从“爸爸”移到“妈妈”,并在“彼得”下添加一个新的孩子2“吉尔”

Parent: "Dad"
  Child1s (0)
Parent: "Mom"
  Child1s: (1)
  -> Child1: "Peter"
     Child2s (1)
     -> Child2: "Jill"

using(var context = new FamilyDbContext())
{
    var parent1 = context.Parents.Single(x => x.Name == "Dad");
    var parent2 = new Parent {Name = "Mom"};
    var child = parent1.Child1s.Single(x => x.Name == "Peter");
    parent1.Children.Remove(child);
    parent2.Children.Add(child);
    child.Parent = parent2;
    var grandChild = new Child2{Name = "Jill", Child = child};
    child.Child2s.Add(grandChild);
    context.SaveChanges();
}

不要尝试在子级上更新“ ParentID”等,而是在要在父级之间移动实体的情况下更新引用。 EF将管理FK。

编辑:如果Child1存在而没有可选的父级,并且您想要向其添加一个Child2并将其关联到新的父级:

using(var context = new FamilyDbContext())
{
    var child = context.Child1s.Single(x => x.Name == "Peter");
    var parent = new Parent {Name = "Dad"};
    var grandChild = new Child2 { Name = "Jill", Child1 = child };
    child.Parent = parent;
    parent.Child1s.Add(child);

    context.SaveChanges();
}

要注意的是实体和不断变化的关联等,是要确保所有有问题的实体都与同一个DbContext实例关联。通常,您会发现将实体作为参数接受的方法,然后在尝试在新的DbContext下添加实体并关联作为参数传入的实体时遇到问题。这些实体可以是与不同上下文关联的实体,也可以视为导致错误或重复数据的新实体。可以将实体附加到上下文,但是只有当您确定传递的实体可以信任并且尚未与上下文关联时,才需要仔细进行此操作。

因此,以上示例演示了如何在DbContext范围内加载和创建所有受影响的实体。这样的事情可能会引起问题:

public void MoveChild(Child1 child)
{
    using (var context = new FamilyContext())
    {
        var parent = new Parent {Name = "Dad"};
        var grandChild = new Child2 { Name = "Jill", Child1 = child };
        child.Parent = parent;
        parent.Child1s.Add(child);

        context.SaveChanges();        
    }
}

原因是“子级”与我们的上下文无关。它可能与另一个上下文相关联,或者已经被反序列化,从而使其实际上只是一个普通对象而不是被跟踪实体。

要附加它,您可以执行以下操作:

public void MoveChild(Child1 child)
{
    using (var context = new FamilyContext())
    {
        child = context.Child1s.Attach(child);
        var parent = new Parent {Name = "Dad"};
        var grandChild = new Child2 { Name = "Jill", Child1 = child };
        child.Parent = parent;
        parent.Child1s.Add(child);

        context.SaveChanges();        
    }
}

但是,例如,如果DbContext是作用域级别的模块级(而不是using块),或者您正在对可能重复的引用集合或嵌套结构进行操作,则此类代码需要小心参考。如果您附加了已经与上下文关联的实体,则将获得异常。