2016-03-29 10 views
1

Mit EF und C#, ich versuche, einen Klon einer Entität zu machen, die viele verwandte Datensätze hat. Ich möchte auch die zugehörigen Datensätze klonen. Das oberste Objekt ist ein Bid.Entity Framework C# - Cloning-Objekt mit Kindern mit Viele-zu-Viele-Beziehungen

class Bid 
    { 
      Collection<ItemGroup> ItemGroups {get;set;} 
      Collection<Evaluator> Evaluators {get;set;} 
    } 

Kinder ItemGroups und Evaluators zu sein. Sie sind viele zu viele.

class ItemGroup 
{ 
    Collection<Evaluator> Evaluators {get;set;} 
} 

Class Evaluator 
{ 
    Collection<ItemGroup> ItemGroups {get;set;} 
} 

ich klonen die Bid, und alle seine Kinder, indem Sie die Datenbank

Bid bid = dbContext.Bids.AsNoTracking().FirstOrDefault() 
        .Include(b => b.ItemGroups) 
        .Include(b => b.ItemGroups.Select(e => e.Evaluators)) 

und das Hinzufügen der Bid zurück in mit

database.Bids.Add(bid); 
database.SaveChanges(); 

Das Problem ist, das viele-zu abfragt -viele Beziehung zwischen Evaluators und ItemGroups. Da sich ihre Sammlungen gegenseitig referenzieren, wenn Sie das Bid zurück hinzufügen, werden die Datensätze VERDOPPELT.

Also, bevor Klon, habe ich ein Gebot:

Original Bid - 
Number of ItemGroups = 3 
Number of Evaluators = 2 

und nach Klon, ich habe ein neues Gebot, mit:

New Bid - 
Number of ItemGroups = 3 
Number of Evaluators = 6 

was offensichtlich falsch ist. Wie klone ich diese Beziehung, ohne dass EF Dubletten hinzufügt?

Ist das Problem meine ursprüngliche Abfrage? Ich habe alle möglichen Optionen ausprobiert, mit .Include()s, die von Bid -> Evaluators -> Item Groups verfolgen, oder einfach nur gehen Bid -> Evaluator und Bid -> ItemGroup, aber nichts scheint mich ganz was ich will. Jede und jede Hilfe wird sehr geschätzt, und bitte lassen Sie mich einfach wissen, wenn ich einige Klarstellungen anbieten kann. Danke im Voraus.

+0

Möglicherweise haben Sie mehr Glück, wenn Sie die Entität mit aktivierter Verfolgung abrufen und dann den Entitätsstatus vor dem Speichern der Änderungen ändern. https://msdn.microsoft.com/en-us/data/jj592676.aspx Ich glaube nicht, dass dies dazu führen wird, die ItemGroups und Aufzüge in Ihrem Beispiel zu duplizieren, aber ich habe dies nicht getestet. – James

+0

Danke für die Eingabe.Ich bin mir nicht ganz sicher, ob ich das so will, aber es führt zu einem anderen unerwarteten Verhalten beim Klonen von Elementen weiter unten in der Grafik. – kdeez

Antwort

0

Nun, hier ist meine super janky Lösung, bis jemand mir einen besseren Weg sagen kann, es zu tun. Im Grunde lasse ich die Viele-zu-Viele-Beziehungen in meiner Abfrage Include()s aus und suche nur nach bid.ItemGroups und bid.Evaluators.

Ich füge diese als normal, die mir eine Bid mit der entsprechenden Anzahl von Artikelgruppen und 0 Evaluatoren, da die ItemGroup -> Evaluator Beziehungen wurden nicht eingerichtet, weil ich nicht für sie abfragen.

Dann, nach dem Aufruf database.Bids.Add(bid), ich re-Abfrage für das ursprüngliche Gebot und es ist Evaluator/ItemGroup Beziehungen, und manuell alle Evaluator/ItemGroup Referenzen mit Namen/IDs/was auch immer Bezeichner verfügbar sind.

List<Evaluator> originalEvals = db.Bids.Where(b => b.Id == entityId) 
       .Select(b => b.Evaluators) 
       .FirstOrDefault() 
       .ToList(); 
      foreach(Evaluator origEval in originalEvals) 
      { 
       db.Entry(origEval).Reference(e => e.ClientUser).Load(); 
       db.Entry(origEval).Collection(e => e.ItemGroups).Load(); 
      } 

      foreach (Evaluator newEval in bid.Evaluators) 
      { 
       Evaluator originalEval = originalEvals.Where(e => e.ClientUserId == newEval.ClientUserId).FirstOrDefault(); 

       foreach (ItemGroup ig in originalEval.ItemGroups) 
       { 
        newEval.ItemGroups.Add(bid.ItemGroups.Where(g => g.Name == ig.Name).FirstOrDefault()); 
       } 
      } 

Shitty, aber es funktioniert.