C# 实体框架插入父子孙对象

C# 实体框架插入父子孙对象,c#,entity-framework,C#,Entity Framework,我正在尝试插入一个包含n个子项的父实体,该子实体可以进一步包含n个自己的子项。当我插入一个没有子对象的对象时,一切正常,但一旦输入对象包含子对象,就会在Context.SaveChanges()上显示以下错误: “操作失败:无法更改关系,因为一个或多个外键属性不可为null。对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。” 家长: public class Parent : Entity {

我正在尝试插入一个包含n个子项的父实体,该子实体可以进一步包含n个自己的子项。当我插入一个没有子对象的对象时,一切正常,但一旦输入对象包含子对象,就会在Context.SaveChanges()上显示以下错误:

“操作失败:无法更改关系,因为一个或多个外键属性不可为null。对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。”

家长:

 public class Parent : Entity
    { 
        public Parent()
        {
            this.Children = new HashSet<Children>();
        }        
        public virtual ICollection<Child> Children { get; set; }
    }
以下是我的DBContext:

    modelBuilder.Entity<Child>().ToTable("Children")
        .HasRequired<Parent>(x => x.Parent);

    modelBuilder.Entity<GrandChild>().ToTable("GrandChildren")
        .HasRequired<Child>(y => y.Child);

    modelBuilder.Entity<Parent>().ToTable("Parents")
        .HasMany(z => z.Child)
        .WithRequired(i => i.Parent); 

插入似乎没有问题。似乎我一直在错误的地方寻找问题。

的确,我知道这将是一个固定的最大3深度,所以我采用了这种设计,但我会记住你所说的。在主题上,我通过将diffParent映射到DTO,然后进行拾取和后续操作,解决了这个问题将其映射回我传递给insert方法的实体列表。

您可能为该问题编写了此代码,这是可以的,但在这种情况下不太可能发生异常。是否在实际代码中,您重新分配了现有(grand)值其他父母的子女?谢谢你的评论,你说得对。代码确实是用于演示的。至于现有部分:我将所有的子女和孙子作为新对象生成,我唯一接触现有实体的时间是在我迭代输入实体列表时。你能修改代码使其更接近真实的实体吗代码。感兴趣的部分是输入实体是否附加到上下文,以及在设置子属性时是否设置了任何引用属性。我引用输入列表中每个实体的Id,并将其添加为每个子项的属性。我将其添加到代码列表中。其他属性只是硬编码值或作为输入属性输入的值,并且这些值都没有链接到任何实体。
parent.Child.Add(Child);
应该是
parent.Children.Add(Child);
?另外,如果已经在循环中执行了,为什么要在循环后执行此操作?
Child.granner.Add(granner)
alkso看起来应该是
child.grandrenes.Add(grandren);
在我们开始查找错误代码之前,您能仔细检查您的代码并确保它反映您的实际代码吗?
 public class GrandChild : Entity
    {
        public int ChildId { get; set; }       
        public virtual Child Child { get; set; }
    }  
    modelBuilder.Entity<Child>().ToTable("Children")
        .HasRequired<Parent>(x => x.Parent);

    modelBuilder.Entity<GrandChild>().ToTable("GrandChildren")
        .HasRequired<Child>(y => y.Child);

    modelBuilder.Entity<Parent>().ToTable("Parents")
        .HasMany(z => z.Child)
        .WithRequired(i => i.Parent); 
public Parent Insert(List<AnotherObject> input)    
        {                   
            Parent parent = new Parent();

            // Set parent attributes
            foreach (var x in input)
            {
                Child child = new Child();
                // Set child attributes
                // EDIT: I also set an attribute based on the list of 
                // entities from the input
                child.OtherObjectId =  x.Id;
                child.Parent = parent;                                

                if (x.Children.Count > 0)
                {
                    foreach (var y in x.Children)
                    {
                        GrandChild grandChild = new GrandChild();
                        // Set grandChild attributes

                        grandChild.Child = child;
                        child.GrandChildren.Add(grandChild);
                    }
                }
                parent.Children.Add(child);
            }

            Context.Parents.Add(parent);
            Context.SaveChanges();
        }
        Random rand = new Random(DateTime.Now.ToString().GetHashCode());
        var selected = diffParent.DiffChild.OrderBy(x => rand.Next()).Take(diffParent.AmountShown).ToList();
        foreach (var q in selected)
        {
            var listOne = new List<DiffChild>();
            var listTwo = new List<DiffChild>();
            if (q.CountAttribute != null)
                listOne  = q.DiffChild.Where(c => c.Attribute == true).OrderBy(x => rand.Next()).Take((int)q.CountAttribute).ToList();
            if (q.OtherCountAttribute != null)
                listTwo = q.DiffChild.Where(d => d.Attribute != true).OrderBy(y => rand.Next()).Take((int)q.OtherCountAttribute).ToList();
            q.DiffChildren = listOne.Concat(listTwo).ToList();
        }
var selected = diffParent.DiffChild.OrderBy(x => rand.Next()).Take(diffParent.AmountShown).ToList();