Problem: Mehrfache Linq-Abfrage

  • C#

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von ptbberlin.

    Problem: Mehrfache Linq-Abfrage

    Hallo,
    der Titel ist evt. nicht ganz klar, aber mir fällt nichts besseres ein.
    Es geht um folgendes:

    in meiner Anwendung soll folgender Code vereinfacht werden:

    Quellcode

    1. if (selected.Modul == 1)
    2. {
    3. var arQuery = (from acp in Admin.conn.ModulMikro where acp.Grunddaten_ID == gdID select acp).FirstOrDefault(); // Admin.conn enthält DataContext
    4. if (arQuery == null)
    5. {
    6. return;
    7. }
    8. foreach (PropertyInfo info in arQuery.GetType().GetProperties())
    9. {
    10. if (info.CanRead)
    11. {
    12. //NULL-Value abfangen
    13. if (info.GetValue(arQuery, null) == null)
    14. {
    15. myValue = "";
    16. }
    17. else myValue = info.GetValue(arQuery, null).ToString();
    18. myModule.Add(info.Name, myValue);
    19. }
    20. }
    21. }
    22. else if (selected.Modul == 2)
    23. {
    24. var arQuery = (from acp in Admin.conn.Exponate where acp.Grunddaten_ID == gdID select acp).FirstOrDefault();
    25. if (arQuery == null)
    26. {
    27. return;
    28. }
    29. foreach (PropertyInfo info in arQuery.GetType().GetProperties())
    30. {
    31. if (info.CanRead)
    32. {
    33. //NULL-Value abfangen
    34. if (info.GetValue(arQuery, null) == null)
    35. {
    36. myValue = "";
    37. }
    38. else myValue = info.GetValue(arQuery, null).ToString();
    39. myModule.Add(info.Name, myValue);
    40. }
    41. }
    42. }
    43. DGCurrModul.ItemsSource = myModule;


    Wie zu erkennen, ändert sich nur die Tabelle in der Linq-Abfrage -> Admin.conn.ModulMikro wird zu Admin.conn,Exponate, der Rest bleibt gleich. Nach gleichem Muster sollen weitere Tabellen aufgerufen werden.
    Ich habe versucht, die Variable arQuery als Public zu deklarieren, bin aber damit nicht weiter gekommen.

    Für Tipps/Hinweise wäre ich dankbar :)
    Anmerkung noch: Ich bin gerade erst von VB.Net nach C# mit Linq umgestiegen und also noch ziemlich unbedarft <X

    PTBBerlin
    Jo, mittm ?.-Operator und mit ?? lässt sich das schon gehörig eindampfen, und wenn man auch noch das kompaktere {}-Layout im Visuialstudio einstellt, kommt man bei 13 Zeilen raus

    C#-Quellcode

    1. PropertyInfo[] infos;
    2. if (selected.Modul == 1) {
    3. infos = Admin.conn.ModulMikro.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    4. }
    5. else if (selected.Modul == 2) {
    6. infos = Admin.conn.Exponate.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    7. }
    8. foreach (PropertyInfo info in infos) {
    9. if (info.CanRead) {
    10. myValue = info.GetValue(arQuery, null)?.ToString() ?? "";//NULL-Value abfangen
    11. myModule.Add(info.Name, myValue);
    12. }
    13. }

    Ich würde hier sogar {}-freies, einzeiliges if verwenden, obwohl dann die Zeile ziemlich lang und somit schlechter lesbar wird:

    C#-Quellcode

    1. PropertyInfo[] infos;
    2. if (selected.Modul == 1) infos = Admin.conn.ModulMikro.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    3. else if (selected.Modul == 2) infos = Admin.conn.Exponate.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    4. foreach (PropertyInfo info in infos) {
    5. if (info.CanRead) {
    6. myValue = info.GetValue(arQuery, null)?.ToString() ?? "";//NULL-Value abfangen
    7. myModule.Add(info.Name, myValue);
    8. }
    9. }
    Vorteil davon ist, dass die verschiedenen Varianten (es sollen ja noch einige hinzukommen) jeweils nur eine Zeile einnehmen und somit untereinander stehen - das erhöht in dieser Beziehung die Lesbarkeit sehr stark, und überwiegt.

    Den Linq-Ausdruck selbst kann man nicht zusammenfassen, es sei denn, der Datentyp von ModulMikro und Exponate ist identisch.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Danke für die schnelle Antwort.
    Mit PropertyInfo muss ich mich noch befassen, kannte ich noch nicht.

    Habe zum Test deinen Code einmal eingefügt, bekomme jedoch einen Fehler

    Quellcode

    1. foreach (PropertyInfo info in infos)
    2. {
    3. if (info.CanRead)
    4. {
    5. myValue = info.GetValue(infos, null)?.ToString() ?? "";//NULL-Value abfangen
    6. myModule.Add(info.Name, myValue);
    7. }
    8. }

    bei der Foreach-Schreife: Fehler CS0165 Verwendung der nicht zugewiesenen lokalen Variablen "infos". Obwohl mit "PropertyInfo[] infos;" vor der if-Schleife deklariert und mit der Linq-Abfrage zugewiesen??
    jo, ich konnte den Code nicht testen, weil ich deine table-Dinger ja nicht hab.
    Zum Fehler: Der Compiler erkennt, dass es auftreten kann, dass keine der if-else if - Bedingungen greift, und dann ist infos nicht zugewiesen, und würde einen Laufzeitfehler auslösen.
    Da es eh zu Problemen kommt, wenn keine der Bedingungen zutrifft, empfiehlt sich, durch ein abschliessendes else da Vorsorge zu treffen:

    C#-Quellcode

    1. PropertyInfo[] infos;
    2. if (selected.Modul == 1) infos = Admin.conn.ModulMikro.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    3. else if (selected.Modul == 2) infos = Admin.conn.Exponate.FirstOrDefault(acp => acp.Grunddaten_ID == gdID)?.GetType().GetProperties();
    4. else throw new Exception("unknown Modul-Value");
    5. foreach (PropertyInfo info in infos) {
    6. if (info.CanRead) {
    7. myValue = info.GetValue(arQuery, null)?.ToString() ?? "";//NULL-Value abfangen
    8. myModule.Add(info.Name, myValue);
    9. }
    10. }


    ptbberlin schrieb:

    Mit PropertyInfo muss ich mich noch befassen, kannte ich noch nicht.
    Nanu?
    PropertyInfo taucht doch in deim Code aus post#1 auf - das nix gutt, Code schreiben mit Datentypen, die man noch nie gesehen hat.
    Das ist iwo herkopiert, oder wie kommts dazu?
    Weisst du denn, was der Code tun soll?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades,
    Zu 1: Prima, Fehler behoben. Danke.
    Zu 2: Ich gestehe, ist geklaut ;( . Was der Code tun soll, ist schon klar: Ich brauche aus der jeweils zugrunde liegenden Tabelle neben den Werteren (Value) auch den Feld-Namen (Name), um die jeweils ausgewählte Detail-Tabelle mit Feldnamen und -Inhalt anzuzeigen. Habe nach langem Suchen die Property-Abfrage gefunden und zunächst einmal ausprobiert (mit Erfolg). Bin aber jetzt gerade dabei, mich einzulesen (docs.microsoft.com/de-de/dotne…nfo?view=netframework-4.8).

    PTBBerlin