我试图插入一个有n个孩子的父实体,这些孩子可以进一步拥有自己的孩子。当我插入一个没有孙子的对象时,一切正常,但只要输入对象包含孙子,就会在Context.SaveChanges()上显示以下错误:
"操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。"
父:
public class Parent : Entity
{
public Parent()
{
this.Children = new HashSet<Children>();
}
public virtual ICollection<Child> Children { get; set; }
}
子:
public class Child : Entity
{
public Child ()
{
this.GrandChildren = new HashSet<GrandChild>();
}
public virtual ICollection<GrandChild> GrandChildren { get; set; }
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
孙:
public class GrandChild : Entity
{
public int ChildId { get; set; }
public virtual Child Child { 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);
然后最后我的插入如下,我根据另一个输入对象有条件地建立一个新的父子孙对象(我试图根据类似的亲子 - 保存问卷的初始状态 - 孙子问卷对象层次结构):
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();
}
编辑:问题似乎源于所选列表,并且更具体来自for循环,我尝试从完整列表中选择特定实体,如果我只传递这个:
var selected = diffParent.DiffChild.OrderBy(x => rand.Next()).Take(diffParent.AmountShown).ToList();
插入似乎没有问题。似乎我一直在寻找错误地方的问题。
答案 0 :(得分:0)
确实如此,我知道这将是一个固定的最大深度3,所以我采用了这种设计,但我会记住你的想法。关于主题我设法通过将diffParent映射到DTO,然后执行拾取并将其映射回我传递给insert方法的实体列表来解决此问题。