2016-07-13 9 views
0

Ich habe Probleme damit, meine LINQ-Abfragen effizient zu strukturieren, so dass ich die Anzahl der Roundtrip-Aufrufe an die Datenbank minimieren kann.Benötigen Sie eine effizientere Möglichkeit, viele Entitäten zu erstellen

Mit dem aktuellen Code unten kann jede dieser Objektkreationen zahlreiche offene und geschlossene Datenbankverbindungen erzeugen.

Wie könnte ein Teil dieses Codes neu strukturiert werden, um die Aufrufe an die Datenbank zu minimieren und mehr Objekte in einzelne Aufrufe einzufügen?

Ich habe auch mehrmals auf SaveChanges aufgerufen, um Probleme von Objekten, die nicht im Kontext vorhanden sind, zu tun, bis ich die Änderungen speichere.

public IActionResult AddSnapshots([FromBody]List<MembershipSnapshot> snapshots, bool? update = false) 
     { 
      if (!ModelState.IsValid) { return new BadRequestObjectResult(ModelState); } 
      if (snapshots.Count == 0) 
      { 
       ModelState.AddModelError("Empty", "There were no records provided to be inserted."); 
       return new BadRequestObjectResult(ModelState); 
      } 

      // Get the composite keys from the supplied list 
      var snapshotKeys = snapshots.Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray(); 
      // Find which records already exist in the database, pulling their composite keys 
      var snapshotsInDb = platformContext.MembershipSnapshots.Where(s => snapshotKeys.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate })) 
               .Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray(); 
      // And filter them out, so we remain with the ones that don't yet exist 
      var addSnapshots = snapshots.Where(s => !snapshotsInDb.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate })) 
       .ToList(); 
      platformContext.MembershipSnapshots.AddRange(addSnapshots); 
      platformContext.SaveChanges(); 

      // In addition to adding all of the snapshots that didn't exist, we'll populate the 
      // membership categories, aggregates and aggregate collections if they don't already exist 
      var aggregates = snapshots.Select(s => new { Name = s.Aggregate, Category = s.AggregateCategory }).Distinct(); 

      var addAggregates = aggregates.Where(a => !platformContext.MembershipAggregates.Any(ma => ma.Name == a.Name)) 
              .GroupBy(a => a.Name).Select(g => g.First()) 
              .Select(a => new Aggregate { Name = a.Name }); 
      platformContext.AddRange(addAggregates); 
      platformContext.SaveChanges(); 

      var addCategories = aggregates.Where(a => !platformContext.MembershipCategories.Any(c => c.Name == a.Category)) 
              .GroupBy(a => a.Category).Select(g => g.First()) 
              .Select(a => new Category { Name = a.Category }); 
      platformContext.AddRange(addCategories); 
      platformContext.SaveChanges(); 

      var addAggregateCollection = aggregates.Where(a => !platformContext.AggregateCollections.Any(ma => ma.Name == a.Name)) 
                .GroupBy(a => a.Name).Select(g => g.First()) 
                .Select(a => new AggregateCollection() 
                { 
                 Name = a.Name, 
                 Category = platformContext.MembershipCategories.Where(c => c.Name == a.Category).Single(), 
                 Description = a.Name, 
                 AggregateCollectionAggregates = new List<AggregateCollectionAggregate>() 
                 { 
                  new AggregateCollectionAggregate() 
                  { 
                   Aggregate = platformContext.MembershipAggregates.Where(ma => ma.Name == a.Name).Single() 
                  } 
                 } 
                }); 
      platformContext.AddRange(addAggregateCollection); 
      platformContext.SaveChanges(); 

      return new StatusCodeResult(StatusCodes.Status200OK); 
     } 
+0

Zunächst müssen Sie Änderungen nur einmal am Ende der Methode speichern, und Sie können NULL-Referenz vermeiden, indem Sie die Eigenschaften aus dem Modell initialisieren. –

+0

Ich spreche nicht über Null-Referenz, ich spreche über keine Elemente in dem Kontext, bis ich die Änderungen festschreibe. – twilliams

Antwort

1

Mate, benötigen Sie einen Kellner Sache bei DbContext wie zu in einem Restaurant.

Wenn Sie mit 10 Freunden in einem Restaurant sind, der Kellner ist nicht kommen, um die Reihenfolge der ersten Freund nehmen, dann in die Küche gehen die Informationen an den Mann Koch zu geben, dann ist kommenden zurück für den zweiten Freund wieder gehen bis Küche ... (wenn das so geht, bitte in ein anderes Restaurant gehen).

Der Kellner an den Tisch kommt und bekommen alle Informationen die er braucht und dann an den Mann Koch geht, gleiche mit DbContext, können Sie so viele neue Objekte hinzufügen, wie Sie wollen, wird es über die einzelnen kennen neues Objekt und wird sich nicht beschweren, solange Sie die Objekte initialisieren.

Wie mit dem Kellner, wenn ein guter Kellner weiß, welchen Wein sie haben und was er Ihnen geben kann, wenn Sie um einen anderen Wein bitten, kann er Ihnen von Anfang an sagen "Nein haben wir nicht" weil er ist ein guter Kellner und weiß immer was er hat oder nicht. Damit Ihre Dbcontext gut ist Dbcontext, müssen Sie ihr für jedes Objekt sagen, was dort zu erwarten ist.

ex. der Initialisierung

public class Lunch 
    { 
     public IEnumerable<Meat> Meat { get; set; } = new List<Meat>(); 
     public Desert Desert { get; set; } = new Desert(); 
     public DateTime DateTime { get; set; } = DateTime.Now; 
     public bool WaiterIsFriendly { get; set; } = true; 
    } 

Hoffe, Sie erkennen, wie Sie mit DbContext arbeiten !!!

Edit:

Wenn ich ein Entity in meinem DbContext namens Mittagessen haben, kann ich die folgenden:

var lunch1=new Lunch(); 
Context.Lunch.Add(lunch1); 
    lunch1.Desert=new Desert(); 
    lunch1.Meat.add(new Meat()); 

    var lunch2=new Lunch(); 
Context.Lunch.Add(lunch2); 
    lunch2.Desert=new Desert(); 
    lunch2.Meat.add(new Meat()); 

und am Ende kann ich sagen Context.SaveChanges();

All dies kann nur passieren, wenn ich die Wüste, Fleisch ... in der Mittagsklasse initialisiere.

+0

oben für das kreative Beispiel =) – Progressive

+0

Ich weiß nicht wirklich, was diese Antwort auf den Tisch bringt. Ich verstehe, wie man einen DbContext benutzt.Was Sie nicht verstehen, ist, dass, wenn ich meine neu erstellten Objekte in den Kontext mit AddRange hinzufügen, sind sie nicht verfügbar für den Zugriff von meinem anderen Code ... die Datensätze sind leer. Außerdem ist das nur ein Teil des Problems. Selbst mit einem einzigen SaveChange für den Kontext, wenn alles andere richtig war, öffnet und schließt die Datenbank die Verbindungen für jedes einzelne über AddRange hinzugefügte Objekt. Wenn ich 200 Objekte hinzufüge, öffnet und schließt sich die Datenbank 200 Mal mit meinem aktuellen Code. – twilliams

Verwandte Themen