dedlfix: LINQ

Beitrag lesen

Tach!

Wie man sieht, fehlen bei z.B. Array 2 und 3 einige Tage. Ich muss nun via LINQ aus diesen Array ein Array machen, indem ich die Werte mit denselben Datum miteienader addiere, also:

Wenn ich mir die LINQ-Methoden anschaue, dann denke ich mir, dass die drei Mengen zunächst zu einer verbunden werden sollten. Das geht mit Concat(), was du bei drei Sequenzen (Arrays) zweimal aufrufen musst. Dann hast du eine flache Menge wie in einer Tabelle einer Datenbank. Jetzt darüber ein GroupBy() laufen lassen, das ergibt einen Wert pro Tag und für den als resultSelector ein Sum() auf die Werte anwenden.

Heute hab ich das mal so wie vorgeschlagen nachgestellt (Ausnahme: Union statt Concat). Eine Datenbank mit drei Tabellen, jede mit derselben Struktur. Einmal ID (weils es sein muss), einmal Date und einmal Integer als Felder. Da hat mir das EF logischerweise drei Entity-Types erstellt, die alle so aussahen, aber unterschiedlich hießen. Damit ich die Datensätze miteinander in eine Ergebnismenge bringen konnte, hab ich noch eine einfache Klasse dafür erstellt.

public class Record {  
  public DateTime Date { get; set; }  
  public int Value { get; set; }  
}

Der erste Versuch sah so aus:

List<Record> result = db.Entity1  
  .Select(entity1 => new Record {  
    Date = entity1.Date,  
    Value = entity1.Value  
  })  
  .Union(db.Entity2.Select(entity2 => new Record {  
    Date = entity2.Date,  
    Value = entity2.Value  
  }))  
  .Union(db.Entity3.Select(entity3 => new Record {  
    Date = entity3.Date,  
    Value = entity3.Value  
  }))  
  // .ToList()  
  .GroupBy(record => record.Date.Date, (date, values) => new Record { Date = date, Value = values.Sum(record => record.Value)}).ToList();

Nach dem zweiten Union waren alle Datensätze in einer flachen Struktur vorhanden. Das GroupBy hat dann beim Ausführen gemeckert "The specified type member 'Date' is not supported in LINQ to Entities." Das kann also offensichtlich nicht nach SQL übersetzt werden. Also hab ich vor das GroupBy ein .ToList() eingefügt und hab damit "LINQ to Entities" verlassen. Nun hat das problemlos geklappt. Das Gruppieren und Datumsberechnen wurde wurde damit vom Client erledigt.

Ein Nachteil dieser Methode kann sein, dass die Datenmenge gegebenenfalls recht groß wird, die vom DBMS zum Client übertragen werden und dort verarbeitet werden muss.

Das record.Date.Date (das erste Date ist der Feldnamen, das zweite eine Eigenschaft, die den Datumsanteil eines DateTime liefert) kann gegebenenfalls zu record.Date gekürzt werden, wenn im DBMS lediglich Datümer ohne Zeiten abgelegt sind. Dann ist der Time-Teil ja immer 00:00:00 und es klappt auch ohne das eingefügte ToList().

dedlfix.