Laden...

LinQ-Abfrage die Datensätze mit Nummer vergleicht und den Datensatz mit größtem Datumswert ausgibt

Erstellt von oehrle vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.424 Views
O
oehrle Themenstarter:in
461 Beiträge seit 2009
vor 11 Jahren
LinQ-Abfrage die Datensätze mit Nummer vergleicht und den Datensatz mit größtem Datumswert ausgibt

verwendetes Datenbanksystem: <sqlexpress 2008>

Hallo, fogendes Paoblem. Habe Daten in ein DataSet eingelesen.
EIne Tabelle muss ich noch eine BErechnung durchführen, wie lange der Datensatz schon liegt. In dieser Tabelle liegen Aufträge, mit ihren ganzen Arbeitgängen. das heißt: Der Auftrag mit der AUftragsnummer xxx ist z.B. 10 x drin, da es 10 Arbeitsgänge gibt (1. BEarbeitung auf Maschine A, 2. Bearbeitung auf Maschine B ...). Der Datensatz hat dann noch ein Meldedatum, wann er an welcher Maschine war. Nun sollte ich hier noch verstrichenen Tage berechnen, von heute bis zur letzten Bearbeitung der Auftragsnummer. Somit müßte ich jede Auftragsnummer durchlaufen und dann noch alle Arbeitsgänge dieser Auftragsnummer und das größte Datum suchen (ist nach Format yyyyMMdd abgelegt).

Wie mache ihc das in LinQ. Ich hoffe da auf mehr Performance, denn in dieser Tabelle sind 70000 Datensätze.

Ich habe hier mal ein Beispiel. Wenn ich das unten einblende, mit dem .Max()-Auswertung bekomme ich folgenden Fehler: "At least one object must implement IComparable."
Hier mal der Code:


//// Alle Auftragsnummern erstmal vereinzeln (Distinct, und Meldedatum muss ein Datum enthalten)
            var auftragsnummerListe = dataTable.AsEnumerable().OrderBy(order=>order["Auftragsnr"]).Where(x => x["Meldedatum"].ToString() != "0").Select(x => x["Auftragsnr"]).Distinct();

            for (int j = 0; j < auftragsnummerListe.Count(); j++)
            {
                //// Auftragsnummer in Variable speichern
                decimal auftragsNummer = Convert.ToDecimal(auftragsnummerListe.AsEnumerable().ToArray()[j]);

                //// Auftrag mit der Auftragsnummer suchen, welche den größten Datumswert hat. Wie Mache ich das?
                var auftrag = dataTable.AsEnumerable().Where(x => x.Field<decimal>("Auftragsnr") == auftragsNummer)
                    .Select(order => new
                                         {
                                             Auftragsnummer = order["Auftragsnr"],
                                             Arbeitsgang = order["Arbeitsgang"],
                                             Meldedatum = order["Meldedatum"]
                                         });        // .Max(c => new { c.Meldedatum }); //==> Wenn ich das einblende, kommt die Meldung "At least one object must implement IComparable."

            }

Kann mir da jemand helfen, wie ich das bei LinQ mit dem IComparable mache?

C
258 Beiträge seit 2011
vor 11 Jahren

Die meldung sagt dir das sich deine anonyme Klasse nicht vergleichern lässt,
auch dadurch das die DataTable nur Objekte enthält, ist nicht klar wie vergleichen werden soll.

Versuch den Typ bei deiner Anonymen Klasse fest zu legen.

P.S. Mouseover "var" sollte dir anzeigen was für typ es ist.

EDIT: wenn deine format yyyyMMdd ist kannst du auch eine string order machen (wenn MM => 01 ist natürlich)

1.378 Beiträge seit 2006
vor 11 Jahren

Hallo oehrle,

so sollte es ca. funktionieren:


                var auftrag = dataTable.AsEnumerable()
                             .Where(x => x.Field<decimal>("Auftragsnr") == auftragsNummer)
                             .Select(order => new
                                         {
                                             Auftragsnummer = order["Auftragsnr"],
                                             Arbeitsgang = order["Arbeitsgang"],
                                             Meldedatum = order["Meldedatum"]
                                         })
                             .OrderByDescending(c => c.Meldedatum)
                             .FirstOrDefault();
            }

Lg, XXX

O
oehrle Themenstarter:in
461 Beiträge seit 2009
vor 11 Jahren
Funktioniert mit der Lösung, aber sehr langsam

Hallo, danke. Das ic hda nicht selber drauf gekommen bin. Es geht nun, aber braucht ewig lange um die Daten zu aktualisieren.

16.807 Beiträge seit 2008
vor 11 Jahren

Dann probiers mit PLINQ und lass erst am Ende sortieren. Die Menge wäre dafür auf alle Fälle geeignet.
Das Select wird das hunrige sein - nicht das OrderBy.

(Wenn denn wirklich das LINQ der Flaschenhals sein sollte).

1.378 Beiträge seit 2006
vor 11 Jahren

Hallo oehrle,

  • woher kommen denn deine Daten? Kann man die nicht evt. schon vorher filtern?

  • Ein DataTable hat eine RowFilter Eigenschaft mit der man vermutlich noch effizienter Filtern kann.

  • Es kann auch einen marginalen Unterschied machen wie man die Linq-Statements zusammenbaut:

  var auftrag = dataTable.AsEnumerable()
                             .Where(x => x.Field<decimal>("Auftragsnr") == auftragsNummer)
                             .OrderByDescending(c => (DateTime)c["Meldedatum"]) 
                             .Select(order => new
                                         {
                                             Auftragsnummer = order["Auftragsnr"],
                                             Arbeitsgang = order["Arbeitsgang"],
                                             Meldedatum = order["Meldedatum"]
                                         })
                             .FirstOrDefault();

Lg, XXX

O
oehrle Themenstarter:in
461 Beiträge seit 2009
vor 11 Jahren

Hallo, die Daten kommen aus eine gespeicherten Prozedur vom SQL-Server wo ich nicht dran komm (bis jetzt halt noch nicht).
Ich lade die Daten in ein DataSet. Habe die Sortierung vorgezogen, hilft aber nicht viel.

Sollte mal vielleicht doch PLinQ testen, habe mit dem aber noch nie gearbeitet.

1.378 Beiträge seit 2006
vor 11 Jahren

PLinq ist keine Hexerei aber wirklich viel erhoffen darf man sich davon auch nicht. einfach nur nach dem AsEnumerable() ein AsParallel() dranhängen und schon sollten die Abfragen parallel laufen.

Lg, XXX

O
oehrle Themenstarter:in
461 Beiträge seit 2009
vor 11 Jahren
erledigt

erledigt