为什么EF6有这种奇怪的行为?

时间:2017-04-06 13:36:32

标签: c# asp.net entity-framework-6

我有以下情况:

我的EF6数据库中有一个Parent实体第一个数据模型

public partial class Parents
{
    public Parents()
    {
        this.Childs = new HashSet<Childs>();
    }

    public int IdParent { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Childs> Childs { get; set; }
}

Child实体

public partial class Childs
{
    public int IdChild { get; set; }
    public int IdParent { get; set; }
    public string Description { get; set; }

    public virtual Parents Parents { get; set; }
}

然后我填充对象:

Parents parent = new Parents();
parent.Description = "Test parent";

List<Childs> childList = new List<Childs>();

childList.Add(new Childs { Description = "Test child 1" });
childList.Add(new Childs { Description = "Test child 2" });

现在我做这个操作:

using (CUSTOMER_Entities context = new CUSTOMER_Entities())
{
    //adding parent and childs to the context (WITHOUT ANY LINK OR FOREING KEY SET)

    context.Parents.Add(parent);

    context.Childs.AddRange(childList);

    context.SaveChanges();

}

我的问题是:为什么在SaveChanges之后我将孩子们保存在数据库中并使用正确的&#34; IdParent&#34;?

通常我会这样做:

using (CUSTOMER_Entities context = new CUSTOMER_Entities())
{

    context.Parents.Add(parent);

    foreach (var child in childList)
    {
        parent.Childs.Add(child);
    }

    context.SaveChanges();
}

using (CUSTOMER_Entities context = new CUSTOMER_Entities())
{

    context.Parents.Add(parent);

    foreach (var child in childList)
    {
        child.IdParent = parent.IdParent;

        context.Childs.Add(child);
    }
}

什么是正确的方法?

2 个答案:

答案 0 :(得分:1)

(我将为实体和参考使用单数名称)

EF连接父母和孩子的原因是Parent的{​​{1}} = 0且孩子都有Id = 0。

在幕后,EF始终执行关系修正。这是一个EF尝试将导航属性(如IdParentChild.Parent)与原始主键和外键值(Parent.ChildrenId)同步的过程。将子项添加到上下文后,EF连接父项和子项,因为键值(PK和FK)为0。

当EF插入数据时,它首先插入父数据。它会立即从数据库中获取其生成的PK值,并在保存之前将其写入子项的IdParent属性。

您可以通过手动设置来覆盖此自动关联设置。假设您要插入两个有孩子的父母:

IdParent

这会导致异常,因为不能将孩子分配给两个父母。但如果你这样做......

context.Parents.Add(parent);
context.Parents.Add(parent2);

context.Childs.AddRange(childList);

...您已手动设置关联,EF很高兴。

答案 1 :(得分:0)

有多种方法可以做到这一点,我自己对EF很新,所以我不确定一个人是否有优势。

EF应该为您处理大部分FK关系,即使您可以根据需要手动指定。

EX1:

Parents P = New Parent();
P.Childs.Add(New Childs());
context.Parents.Add(P); 
//Now child is part of this particular parent's collection, it should be able
//to determine which foreign key to use automatically when you...
context.SaveChanges();

EX2:

//Code here to pull parent
Parents P = context.Parents.Find(ParentID);
//Assign child to said parent during instantiation
Childs C = new Childs{ Description = "Test", Parents = P};
context.Childs.Add(C);
context.SaveChanges();

EX3:

//Use convention or annotations
//convention naming for foreign key
public partial class Childs
{
    public int IdChild { get; set; }
    //public int IdParent { get; set; }
    public int ParentsID {get; set;}// <---
    public string Description { get; set; }

    public virtual Parents Parents { get; set; }
}

例如3,另请参阅:https://msdn.microsoft.com/en-us/library/jj679962(v=vs.113).aspx