Reputation: 13
I have the following situation:
I have a Parent
entity in my EF6 database first datamodel
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; }
}
and a Child
entity
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; }
}
Then I populate the objects:
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" });
Now I do this operation:
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();
}
My question is: why after SaveChanges I have childs saved in db with correct "IdParent"?
Usually I do:
using (CUSTOMER_Entities context = new CUSTOMER_Entities())
{
context.Parents.Add(parent);
foreach (var child in childList)
{
parent.Childs.Add(child);
}
context.SaveChanges();
}
or
using (CUSTOMER_Entities context = new CUSTOMER_Entities())
{
context.Parents.Add(parent);
foreach (var child in childList)
{
child.IdParent = parent.IdParent;
context.Childs.Add(child);
}
}
What is the right way?
Upvotes: 1
Views: 101
Reputation: 109079
(I'm going to use singular names for entities and references)
The reason why EF connects the parents and children is that Parent
has an Id
= 0 and the children all have IdParent
= 0.
Under the hood, EF always executes relationship fixup. This is a process in which EF tries to synchronize navigation properties (like Child.Parent
and Parent.Children
) with primitive primary key and foreign key values (Id
, IdParent
). After the children are added to the context, EF connects the parent and the children because the key values (PK and FK) are 0.
When EF inserts the data, it first inserts the parent. It immediately grabs its generated PK value from the database and writes it into the IdParent
property of the children before saving them.
You can override this automatic setting of associations by setting them manually. Suppose you want to insert two parents with children:
context.Parents.Add(parent);
context.Parents.Add(parent2);
context.Childs.AddRange(childList);
This would cause an exception, because the children can't be assigned to two parents. But if you do ...
parent.Children = childList;
context.Parents.Add(parent);
context.Parents.Add(parent2);
... you've set the association manually and EF is happy.
Upvotes: 1
Reputation: 140
There are multiple ways to do this, I'm quite new to EF myself so I'm not sure if one has an advantage over the other.
EF should handle most of the FK relations for you, even though you can specify manually if you want to.
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; }
}
For example 3, see also: https://msdn.microsoft.com/en-us/library/jj679962(v=vs.113).aspx
Upvotes: 0