2017-04-06 5 views
1

Ich habe die folgende Situation:Warum dieses merkwürdige Verhalten mit EF6?

Ich habe eine Parent Einheit in meiner EF6 Datenbank erstes Datenmodell

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; } 
} 

und eine Child Einheit

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; } 
} 

Dann füllen ich die Objekte:

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" }); 

Jetzt mache ich diese 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(); 

} 

Meine Frage ist: Warum nach Savechanges Ich habe Childs in db mit der richtigen "IdParent" gespeichert? Normalerweise

ich tun:

using (CUSTOMER_Entities context = new CUSTOMER_Entities()) 
{ 

    context.Parents.Add(parent); 

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

    context.SaveChanges(); 
} 

oder

using (CUSTOMER_Entities context = new CUSTOMER_Entities()) 
{ 

    context.Parents.Add(parent); 

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

     context.Childs.Add(child); 
    } 
} 

Was ist der richtige Weg?

Antwort

1

(Ich werde verwenden Singuläre Namen für Entitäten a nd Referenzen)

Der Grund, warum EF, die Eltern und Kinder verbindet ist, dass Parent hat eine Id = 0 und die alle Kinder haben IdParent = 0.

Unter der Haube EF führt immer Beziehung Fixup. Dies ist ein Prozess, bei dem EF versucht, Navigationseigenschaften (wie Child.Parent und Parent.Children) mit primitiven Primärschlüssel- und Fremdschlüsselwerten (Id, IdParent) zu synchronisieren. Nachdem die untergeordneten Elemente dem Kontext hinzugefügt wurden, verbindet EF das übergeordnete Element und die untergeordneten Elemente, da die Schlüsselwerte (PK und FK) 0 sind.

Wenn EF die Daten einfügt, wird zuerst das übergeordnete Element eingefügt. Es ergreift sofort seinen generierten PK-Wert aus der Datenbank und schreibt ihn in die IdParent-Eigenschaft der Kinder, bevor er sie speichert.

Sie können diese automatische Einstellung von Verknüpfungen überschreiben, indem Sie sie manuell festlegen.Angenommen, Sie zwei Eltern mit Kindern einfügen wollen:

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

context.Childs.AddRange(childList); 

Dies würde eine Ausnahme verursachen, weil die Kinder können nicht zwei Eltern zugeordnet werden. Aber wenn Sie ...

... Sie haben die Zuordnung manuell festgelegt und EF ist glücklich.

0

Es gibt mehrere Möglichkeiten, dies zu tun, ich bin ziemlich neu in EF selbst, also bin ich mir nicht sicher, ob man einen Vorteil gegenüber dem anderen hat.

EF sollte die meisten FK-Beziehungen für Sie übernehmen, auch wenn Sie manuell angeben können, wenn Sie möchten.

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; } 
} 

Zum Beispiel 3, siehe auch: https://msdn.microsoft.com/en-us/library/jj679962(v=vs.113).aspx

Verwandte Themen