Probleme mit Linq Abfrage

  • VB.NET
  • .NET (FX) 4.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Probleme mit Linq Abfrage

    Mit folgender funktionierender Linq Abfrage 3er Tabellen aus einem Typ DS war ich bisher glücklich:


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim rwGeräte = DirectCast(DirectCast(BSTblGeräteLinq.Current, DataRowView).Row, DS.tblGeräteRow)Dim GerätemessungenNachGerät = From k In DS.tblKunden _Join g In DS.tblGeräte On k.ID Equals g.FKKunde _Join m In DS.tblMessungen On g.ID Equals m.FKGerätWhere g.Bezeichnung = CStr(rwGeräte.Bezeichnung)Select m.Besonderheiten, g.Bezeichnung, g.Baujahr, k.Kürzel
    2. dgvFilterNachGerät.DataSource = GerätemessungenNachGerät.ToList
    3. dgvFilterNachGerät.Refresh()




    Nun ist das Problem, dass ich das Abfrage Ergebnis an List und Label übergebe und die Struktur hier anonymisiert ist (siehe Bild).

    Daher war meine Idee, die Abfrage an eine Datatable zu übergeben die dann wieder typisiert ist?
    Das Problem ist nämlich, dass bei jeder klitzekleinen Änderungen die anonymen Bezeichner mit anderen Werten an List und Label übergeben werden und in der Folge natürlich auch die Formulare geändert werden müssen.


    Ich habe daher google gefragt und eine .copytodatatable Methode gefunden die jedoch bei mir nicht zur Auswahl steht.

    Hier bin ich, wieder einmal am Ende meines Verständnisses angekommen.

    Wieso werden die Daten egtl. Anonym übergeben obwohl sie typisiert abgefragt wurden?
    Bilder
    • anonyme typen.JPG

      20,79 kB, 270×313, 119 mal angesehen
    Gruß Hannes

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hans im glück“ ()

    Du kannst mit minimalem Aufwand dir generische Tupel erstellen, die sind zwar generisch, aber nicht anonym:

    VB.NET-Quellcode

    1. Dim bezeichnung = DirectCast(DirectCast(BSTblGeräteLinq.Current, DataRowView).Row, DS.tblGeräteRow).Bezeichnung
    2. Dim query = From k In DS.tblKunden
    3. Join g In DS.tblGeräte On k.ID Equals g.FKKunde
    4. Join m In DS.tblMessungen On g.ID Equals m.FKGerät
    5. Where g.Bezeichnung = bezeichnung
    6. Select Tuple.Create(m.Besonderheiten, g.Bezeichnung, g.Baujahr, k.Kürzel)
    7. Dim GerätemessungenNachGerätTuples = query.tolist
    Bisserl unschön ist, dass Tupel-Properties vorgegebene Benamungen haben, aber vlt. kann man son bischen Quick & Dirty ausnahmsweise verkraften (kenne L & L nicht)
    Danke,
    habs getestet. Bei einer weiteren Linq Abfrage meiner Anwendung kommt bei einer Anzahl von 32 "selecteten Felder" folgender Fehler:

    Quellcode

    1. Fehler bei der ÜBerladungsauflösung, da keine zugreifbare Create diese Anzahl von Argumenten akzeptiert.


    Des weiteren hilft mir der Tuple nicht weiter, es wird quasi noch untypisierter übergeben da nun auch die Felder/Spalten anonymisiert sind (wurden in Item umbenannt) und auch der Tuple in abhängigkeit der Anzahl der ausgewerteten Spalten umbenannt wird (siehe Foto).


    Besteht keine Möglichkeit das ganze in eine temporäre Datatable zu verfrachten?


    Edit Schreibfehler
    Gruß Hannes
    naja, eine untypisierte DataTable kannst du ja jederzeit erzeugen, und ihr beliebig viele Columns adden, auch inklusive Typ-Angabe.
    und eine untypisierte DataRowCollection hat auch eine Add-Methode, glaub sogar auch mehrere Überladungen.

    Oder halt für L & L besondere typisierte DataTables erstellen, evtl. sogar in einem Extra-Dataset, noch eventueller gar in einem Extra-L&L-DataExport-Projekt.
    ...ich könnte mir sogar vorstellen im DS eine typisierte Datatable zu designen die zur Abfrage passt da sich diese "im finalen Zustand" nicht mehr ändern wird.

    Mein Problem ist nur, dass die query der Linq Abfrage derzeit eine große Unbekannte ist, d.h. ich stehe völlig auf dem Schlauch und weiß nicht wie ich den abgefragten Inhalt in die Tabelle verfrachten könnte wenn ich sie hätte...
    Gruß Hannes

    ErfinderDesRades schrieb:

    na, ebenso, wie man jeder anneren typisierten DataTable Rows added: mit der AddTabelleWennIchSieHätteRow() - Methode.


    das ist klar, aber der inhalt der query.
    also zum bsp

    Quellcode

    1. for each datensatz in query
    2. AddTabelleWennIchSieHätteRow()
    3. next
    Gruß Hannes
    ja, was?

    VB.NET-Quellcode

    1. Dim bezeichnung = DirectCast(DirectCast(BSTblGeräteLinq.Current, DataRowView).Row, DS.tblGeräteRow).Bezeichnung
    2. Dim query = From k In DS.tblKunden
    3. Join g In DS.tblGeräte On k.ID Equals g.FKKunde
    4. Join m In DS.tblMessungen On g.ID Equals m.FKGerät
    5. Where g.Bezeichnung = bezeichnung
    6. Select m.Besonderheiten, g.Bezeichnung, g.Baujahr, k.Kürzel
    7. For Each itm In query
    8. DS.TabelleWennIchSieHätte.AddTabelleWennIchSieHätteRow(itm.Besonderheiten, itm.Bezeichnung, itm.Baujahr, itm.Kürzel)
    9. Next

    wenn das gleich funktioniert springe ich nach dieser vorlage freiwillig aus dem fenster (symbolisch, sitze im keller :) )


    Edit: Ach wie ist das schön....
    Streckenweise selbst geheilt :) aber vielen Dank!



    VB.NET-Quellcode

    1. ​For Each Datensatz In GerätemessungenNachGerät
    2. DS.tblTempNachGerät.AddtblTempNachGerätRow(Datensatz.Besonderheiten, Datensatz.Bezeichnung, Datensatz.Baujahr, Datensatz.Kürzel)
    3. Next

    Gruß Hannes

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hans im glück“ ()

    ich muss noch eine frage anhängen:

    habe nu meine tmpTabelle im ds erstellt und fülle diese mit den Daten der Linq Listung.

    Nun habe ich das Problem, dass DBNULL in der Temptabelle nicht akzeptiert wird, bzw. die Exception kommt.

    Ich habe jedoch allow DB Null im Designer aktiv gesetzt?

    Problem besteht vor allem in einem Datumsfeld das nur gefüllt werden soll wenn ein Gerät aussortiert wird, d.h. bei aktiven Geräten steht hier auch kein Datum drin, nur bei inaktiven.

    Was kann ich tun?
    Gruß Hannes
    jo, dassis nervtötend.
    Probierma Nothing anzugeben.

    Ansonsten musste die umständlichere Art des Addens nehmen, die nicht in einem Aufwasch alle Properties entgegennimmt, sondern wo man erst mit tblTabelleWennHättest.NewtblTabelleWennHättestRow eine tblTabelleWennHättestRow erzeugen muss, deren Properties setzen, und wenn fertig adden.

    Und DbNull-Werte kann man ja nicht zuweisen, sondern muss die entweder einfach auslassen, oder man muss tblTabelleWennHättestRow.SetDatumsfeldNull aufrufen.

    (Wie wärs eigentlich, wenn du deine Benamungs-Konvention bisserl überarbeiten tätest? ;) )
    ich hatte nun die idee die tabelle im dataset vor der linq abfrage bei dem entsprechenden feld auf DBNull zu prüfen (Bool Feld).
    Keine der drei Varianten hat funktioniert, Ziel war True zu setzen wenn DBNull ist.


    Wie kann ich denn das prüfen? Das Problem ist, dass bestehende Daten übernommen werden aus vorhandenen XML Projektdateien und das Feld im laufe der Zeit hinzu kam, sollte also künftig den Wert True adden....

    Hinweis: Habe natürlich nicht alle drei Varianten auf einmal getestet sondern nur der einfachheit in die Methode gepackt zur schnelleren Übersicht:

    VB.NET-Quellcode

    1. Private Sub btnGeräteStatusPrüfen_Click(sender As Object, e As EventArgs) Handles btnGeräteStatusPrüfen.Click
    2. Dim sb As String = ""
    3. Try
    4. MessageBox.Show(CStr(DS.tblGeräte.Count) & " schleife wird nun gestartet")
    5. For Each gerät In DS.tblGeräte
    6. 'Variante 1
    7. If Not DBNull.Value.Equals(gerät.GerätAktiv) Then
    8. MessageBox.Show(gerät.GerätAktiv & gerät.Bezeichnung & " hat einen wert")
    9. Else
    10. sb += gerät.Bezeichnung & vbCrLf
    11. gerät.GerätAktiv = True
    12. End If
    13. 'Variante 2
    14. If IsNothing(gerät.GerätAktiv) Then
    15. sb += gerät.Bezeichnung & vbCrLf
    16. gerät.GerätAktiv = True
    17. Else
    18. MessageBox.Show(gerät.GerätAktiv & gerät.Bezeichnung & " hat einen wert")
    19. End If
    20. 'Variante 3
    21. If IsDBNull(gerät.GerätAktiv) Then
    22. sb += gerät.Bezeichnung & vbCrLf
    23. gerät.GerätAktiv = True
    24. Else
    25. MessageBox.Show(gerät.GerätAktiv & gerät.Bezeichnung & " hat einen Wert")
    26. End If
    27. Next
    28. Catch ex As Exception
    29. MessageBox.Show(ex.Message)
    30. End Try
    31. MessageBox.Show("Folgende Geräte hatten keinen zugewiesenen Status:" & vbCrLf & sb)
    32. End Sub



    edit: Und zur Namensgebung, bisher habe ich mich ganz gut zu recht gefunden, für konkrete kritische Hinweise bin ich jederzeit offen.
    Gruß Hannes
    ich weiß jetzt nicht, was das mit der ursprünglichen Frage zu tun hat, aber ist leider wieder untypisierter Crap.
    Guck dir dein Dataset doch mal gelegentlich im ObjectBrowser an, da findest du Methoden wie tblGeräteRow.IsGerätAktivNull As Boolean und tblGeräteRow.SetGerätAktivNull()

    Und ein TryCatch hat in soner Funktion auch nix verloren - lass den Debugger seinen Job machen TryCatch ist ein heißes Eisen