2017-06-09 2 views
0

Ich benutze Entity Framework 6. Wenn ich eine Navigationseigenschaft auf ein Objekt aktualisieren und dann SaveChanges() ausführen, anstatt auf das vorhandene Objekt zu verweisen, erstellt es ein Duplikat in der Referenztabelle .Entity Framework - getrennte Kontexte und doppelte Datensätze

Ich habe einige Beispiele unten:

Das folgende Beispiel funktioniert wie erwartet. Es schafft ein „Kunde“ und eine „Order“ und ordnet sie erfolgreich:

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

Ausgabe

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Allerdings, wenn ich versuche, dann eine Bestellung hinzufügen und meine bestehenden Kunden assoziieren, wenn ich speichere meine Änderungen es das Customer-Objekt in der DB Duplikate sowie die bestehende Ordnung, die ich geschaffen hatte:

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

// Homer Simpson buys some Buzz Cola 

Console.WriteLine("\r\nHomer Simpson is buying Buzz Cola"); 

Order order2 = new Order 
{ 
    Description = "Buzz Cola", 
    Customer = customer 
}; 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Add(order2); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

Ausgabe

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Homer Simpson is buying Buzz Cola 
ConsoleApplication1.Objects.Order - Added 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Wenn ich die Fremdschlüssel im Gegensatz zur Navigation Property gesetzt ist, wird der Datensatz nicht dupliziert. Ich in diesem Szenario jedoch keinen Zugriff auf die Eigenschaften des betreffenden Objekts, bis ich es explizit laden:

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

// Homer Simpson buys some donuts 

Console.WriteLine("\r\nHomer Simpson is buying donuts"); 

Order order3 = new Order 
{ 
    Description = "Donuts", 
    CustomerID = 1 
}; 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null before save!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " before save!"); 
} 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Add(order3); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null after save!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " after save!"); 
} 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Attach(order3); 
    db.Entry(order3).Reference(x => x.Customer).Load(); 
} 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null after forced load!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " after forced load!"); 
} 

Ausgabe

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Homer Simpson is buying donuts 
Customer is null before save! 
ConsoleApplication1.Objects.Order - Added 
Customer is null after save! 
The customer is Homer Simpson after forced load! 

Ist jemand in der Lage irgendwelche Ratschläge zu bieten? Ich verstehe, dass Sie Entitäten manuell anfügen und abtrennen können, aber wenn ich das gesagt habe, arbeite ich mit ziemlich komplizierten Objekten. Ich würde gerne eine einfache Möglichkeit finden, das Change Tracking in Entity Framework zu steuern.

Grüße

Peter Deegan

+0

Keine einfache Möglichkeit - mit getrennten Objektdiagrammen zu arbeiten war nie einfach/einfach in EF. Sie können versuchen, das [GraphDiff] (https://github.com/refactorthis/GraphDiff) -Paket zu versuchen, das versucht, das Thema anzusprechen. Leider wird es vom Autor nicht mehr unterstützt. –

Antwort

0

Wenn Sie Kundenobjekt Befestigung 2 bestellen sie einen neuen Kunden Objekt einfügt, ich glaube, Sie sollten immer anstelle des Anbringens des Unternehmens Fremdschlüssel verwenden, und für das Laden der Eigenschaft Teil, natürlich erhalten Sie nicht das Kundenobjekt an die Bestellung angehängt, da Sie es gerade eingefügt haben, wenn Sie public virtual <T> Add(T entity) überprüfen, wie Sie es das Objekt selbst zurückgeben, ohne andere Objekte, Kundenobjekt gewonnen ' t geladen werden, bis Sie es laden, die Sinn machen Ich schätze, in Ihrem Beispiel verwendeten Sie expl ICIT Last Kundenobjekt zu laden, wenn Sie vermeiden wollen, dass Sie ein träges Laden aktivieren und erhalten immer die Kundenobjekt, ohne es explizit zu laden. Kurz gesagt, verwenden Sie immer fk, und wenn Sie die Entity laden müssen (Lazy Loading oder Explicit), ist das Anhängen von Objekten nie eine gute Übung, es sei denn, Sie möchten alle zusammen einfügen, oder Sie interessieren sich nicht für Duplikate. Ich hoffe das hat geholfen.