一次保存相关实体 - 保存不公开其关系的外键属性的实体时发生错误

时间:2016-12-07 03:16:21

标签: c# entity-framework ef-code-first

(我已查看相关问题,但无法找到答案。)

我正在使用Code First Entity Framework 6进行一些测试。 我有一个孩子"引用两个" Parent"的实体实体。

我想创建子实体和父实体,然后立即保存它们(这样我可以减少db.Save()调用的数量,并将其作为一个工作单元)。< / p>

public class Child
{
    public int ChildID { get; set; }
    public string Name { get; set; }

    public virtual Parent Father { get; set; }
    public virtual Parent Mother { get; set; }
}

public class Parent
{
    public int ParentID { get; set; }
    public string Name { get; set; }

    [ForeignKey("Child")]
    public int? ChildID { get; set; }
    public virtual Child Child { get; set; }
}

(有点令人困惑的设置 - 父母实际上是关系中孩子的#34;孩子&#34;我知道这是一个糟糕的抽象。这只是一个考验。)< / p>

控制器:

    public ActionResult AddWithParents()
    {
        Parent father = new Parent { Name = "Test Father" };
        Parent mother = new Parent { Name = "Test Mother" };

        Child newChild = new Child
        {
            Name = "Test Child",
            Father = father,
            Mother = mother
        };


        db.Children.Add(newChild);

        father.Child = newChild;
        mother.Child = newChild;

        db.SaveChanges();            

        return RedirectToAction("Index");
    }

这样可行,但不会填充Parent.ChildID外键。

如果我做了像father.Child = newChild这样的事情,我会收到以下错误:

  

保存不公开其关系的外键属性的实体时发生错误。 EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅InnerException。       无法确定相关操作的有效排序。由于外键约束,模型要求或存储生成的值,可能存在依赖关系。

有什么方法可以让它发挥作用吗?

1 个答案:

答案 0 :(得分:1)

我在你的代码中找到了问题源:ChildId类中的Parent属性声明为可为空的整数类型,而ChildId类中的Child属性属于非可以为空的整数类型,它们是不同的类型(Nullable<int>int)。

因此,您应该将ChildId类中的Parent属性声明为非可空类型,因此应该解决循环引用问题:

public class Child
{
    public int ChildID { get; set; }
    public string Name { get; set; }

    public virtual Parent Father { get; set; }
    public virtual Parent Mother { get; set; }
}

public class Parent
{
    public int ParentID { get; set; }
    public string Name { get; set; }

    [ForeignKey("Child")]
    public int ChildID { get; set; } // set this FK as non-nullable int
    public virtual Child Child { get; set; }
}

根据this answer,当外键属性数据类型与源主键不匹配或外键属性设置不正确时,会出现循环依赖问题。

编辑:由于ChildId类中的Child属性是数据库表中不可为空的int主键属性,因此删除循环依赖项的最佳方法是设置与主键具有相同数据类型的外键(即int)。

相关问题:

Clean way to deal with circular references in EF?

Unable to determine a valid ordering for dependent operations