Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

LinQ-Abfrage die Datensätze mit Nummer vergleicht und den Datensatz mit größtem Datumswert ausgibt
oehrle
myCSharp.de - Member



Dabei seit:
Beiträge: 404
Herkunft: Germany

Themenstarter:

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

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Console32
myCSharp.de - Member



Dabei seit:
Beiträge: 266

beantworten | zitieren | melden

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)
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Console32 am .
private Nachricht | Beiträge des Benutzers
xxxprod
myCSharp.de - Experte

Avatar #avatar-2329.gif


Dabei seit:
Beiträge: 1420
Herkunft: Österreich\Wien

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
oehrle
myCSharp.de - Member



Dabei seit:
Beiträge: 404
Herkunft: Germany

Themenstarter:

Funktioniert mit der Lösung, aber sehr langsam

beantworten | zitieren | melden

Hallo, danke. Das ic hda nicht selber drauf gekommen bin. Es geht nun, aber braucht ewig lange um die Daten zu aktualisieren.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16205

beantworten | zitieren | melden

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).
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
xxxprod
myCSharp.de - Experte

Avatar #avatar-2329.gif


Dabei seit:
Beiträge: 1420
Herkunft: Österreich\Wien

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
oehrle
myCSharp.de - Member



Dabei seit:
Beiträge: 404
Herkunft: Germany

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
xxxprod
myCSharp.de - Experte

Avatar #avatar-2329.gif


Dabei seit:
Beiträge: 1420
Herkunft: Österreich\Wien

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
oehrle
myCSharp.de - Member



Dabei seit:
Beiträge: 404
Herkunft: Germany

Themenstarter:

erledigt

beantworten | zitieren | melden

erledigt
private Nachricht | Beiträge des Benutzers