为什么这个奇怪的行为与EF6?
问题描述:
我有以下情况:为什么这个奇怪的行为与EF6?
我有一个Parent
实体在我EF6数据库第一数据模型
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后,我已孩子的保存在数据库与正确的“IdParent”?
通常我做:
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);
}
}
什么是正确的方法是什么?
答
(我将使用实体的单数名称a次引用)
为什么EF连接父母和孩子的原因是Parent
有Id
= 0和孩子都IdParent
= 0
引擎盖下,EF始终执行关系修正。这是在其中EF尝试同步与原始主键和外键值(Id
,IdParent
)导航属性(如Child.Parent
和Parent.Children
)的步骤。孩子们被添加到上下文之后,EF连接家长和孩子,因为密钥值(PK和FK)是0
当EF插入数据时,它首先将亲本。它立即从数据库中抓取其生成的PK值,并在保存之前将其写入子女的IdParent
属性中。
您可以通过手动设置来覆盖这些协会的这种自动设置。假设你要插入两个家长带孩子:
context.Parents.Add(parent);
context.Parents.Add(parent2);
context.Childs.AddRange(childList);
这将导致异常,因为孩子不能分配到两个家长。但如果你这样做...
parent.Children = childList;
context.Parents.Add(parent);
context.Parents.Add(parent2);
...你已经手动设置关联,EF很高兴。
答
有多种方法可以做到这一点,我很新的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