Filtern anhand einer Beziehung

  • VB.NET
  • .NET (FX) 4.5–4.8

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

    Filtern anhand einer Beziehung

    Hallo zusammen,

    ich muss erneut bei euch um Hilfe bitten.

    Ich möchte gerne in einem Datagridview z.b. folgendes Statement abbilden.

    SQL-Abfrage

    1. ​SELECT dsShipments.*, dsShipmentPO.PONo
    2. FROM dsShipments INNER JOIN dsShipmentPO ON dsShipments.ShipmentID = dsShipmentPO.ShipmentID
    3. WHERE (((dsShipmentPO.PONo)='1/2017/009'));


    Zur Übersicht das Datenmodel.


    Bei einem simplen Filter such ich wie folgt.

    VB.NET-Quellcode

    1. ​DsShipmentsBindingSource.Filter = "ShipmentID = '" & txtSearch.Text & "'"

    Oder

    VB.NET-Quellcode

    1. ​DataSet.dsShipments.DefaultView.RowFilter = "PONo = '" & txtSearch.Text & "'"


    Das funktioniert allerdings nicht bei Datenfeldern die nicht in der eigenen Table sind.

    Da ich gewiss nicht der erste mit dieser Problematik bin... Wo finde ich die Lösung bzw. nach was muss ich suchen?

    Vielen Dank für eure Hilfe!

    Mit freundlichen Grüßen
    HolyAbsolut
    Um Werte aus verschiedenen Tabellen zusammenzuführen brauchst du in Sql einen Join.
    Im Dgv gibts ähnliches, nur tickt es vollkommen anders.
    Aber wegen der Ähnlichkeit habichs den "JoiningView" genannt. Und es gibt noch 3 weitere Views - also guck dir am besten das Gesamtkonzept an;

    vier Views-Videos
    Hallo,
    danke für die Rückmeldung. Ich glaube das INNER JOIN hat hier etwas irritiert und deplatziert war.

    Zur Übersicht ein Bild der aktuelle und noch langen nicht fertigen GUI.



    Das Datagrid ist an dsShipments gebunden. Die Textbox "Search" ist absichtlich ungebunden da in der finalen Version mit verschiedenen "Begriffen" gesucht werden kann.

    Wenn ich nun nach eine "Begriff" aus der ds Shipment suche funktioniert dies bereits einwandfrei mit:

    VB.NET-Quellcode

    1. ​DsShipmentsBindingSource.Filter = "ShipmentID = '" & txtSearch.Text & "'"


    Jetzt möchte ich dem User noch die Option geben nach der ein PONo suchen zu können die nicht direkt in "dsShipments" gespeicher ist sonder verknüpft in der "dsShipmentsPO" liegt.


    Das Datagrid soll allerdings weiterhin nur die Resultate von "dsShipments" ausgegeben werden.

    Ich meine das dies in dieser Weise nicht in den vier Views ist, oder?

    Vielen Dank für die Hilfe.

    Lg. HolyAbsolut
    Hallo,
    vielen Dank für die rasche Antwort. Ich hatte es bereits davor mit einem Punkt erfolglos versucht.

    PoNo ist ein String.

    Ich habe es daher so versucht

    VB.NET-Quellcode

    1. ​ DsShipmentsBindingSource.Filter = "dsShipmentPO:PONo = '" & txtSearch.Text & "'"


    Fehlermeldung. Zusätzliche Informationen: Syntaxfehler: Fehlender Operand nach dem Operator ':PONo'.

    Habe mir daraufhin nochmal MSDN angeschaut aber die gehen auf diesen Fall nicht ein.

    Daher muss ich fragen wie lautet die richtige Syntax?

    Lg HolyAbsolut
    Hallo,
    nach einer kurzer Recherche zumindest ein kleiner Durchbruch.

    Der Code funktioniert zumindest fehlerfrei.

    VB.NET-Quellcode

    1. DsShipmentsBindingSource.Filter = "Parent(dsCarrierdsShipments).Carrier = 'MSC'"


    Allerdings funktioniert dies nur mit Parents. Wie mach ich das selbe mit Child-tables?

    Eine erste Google suche ist bisher ins leere verlaufen.

    @us4711 Danke für den Tipp. Leider ist die gesuchte Spalte nicht im selben Datatable.

    Lg HolyAbsolut

    HolyAbsolut schrieb:

    Wie mach ich das selbe mit Child-tables?
    Mit Child-Tables ergibt das keinen Sinn.
    Da einem Datensatz immer genau 1 Parent-Datensatz zugeordnet ist, kann man für diesen ParentDatensatz Suchkriterien angeben.
    Aber einem Datensatz sind keine oder viele Child-Datensätze zugeordnet - wie willst du da definieren, was ein Treffer sein soll?
    Hallo,

    ich meine die DB ist korrekt aufgebaut. Lass mich da aber gerne eines besseren belehren.



    Dazu muss mann wissen das die PO zu allererst verfügbar ist und das der Shipmentrecord später folgt.
    Eine PO kann sich auf mehrere Shipments verteilen. Und ein Shipment kann mehrere PO beinhalten.

    Ich wüsste keine andere Lösung unter diesen Voraussetzungen.

    Da das Thema offensichtlich nicht so leicht lösen lassen kann habe ich mir eine kleinen Umweg ausgedacht der zwar nicht sonderlich schön ist aber mir erstmal die Resultat liefert die ich wünsche.

    VB.NET-Quellcode

    1. Sub HaesslichesEntlein(ByVal PoNo As String)
    2. Dim strFilter As String = ""
    3. HWDataSet.dsShipmentPO.DefaultView.RowFilter = "PONo = '" & PoNo & "'"
    4. For Each Row As DataRowView In DataSet.dsShipmentPO.DefaultView
    5. If strFilter = "" Then
    6. strFilter += "ShipmentID = '" & Row.Item("ShipmentID").ToString & "'"
    7. Else
    8. strFilter += " OR ShipmentID = '" & Row.Item("ShipmentID").ToString & "'"
    9. End If
    10. Next
    11. HWDataSet.dsShipmentPO.DefaultView.RowFilter = String.Empty
    12. DsShipmentsBindingSource.Filter = strFilter
    13. End Sub


    Nicht fein aber es funktioniert. :whistling:

    Lg HolyAbsolut
    probierma den hier, das ist typisierter, lässt den DefaultView unbehelligt, und der In-Operator im Filter-Ausdruck ist glaub bisserl performanter:

    VB.NET-Quellcode

    1. Sub HaesslichesEntlein(ByVal PoNo As String)
    2. Dim sShipmentIds = String.Join("', '", From rw In HWDataSet.dsShipmentPO
    3. Where rw.rowstate <> DataRowState.Deleted AndAlso rw.PONo = PoNo
    4. Select rw.ShipmentID)
    5. DsShipmentsBindingSource.Filter = String.Format("PONo in ('{0}')", sShipmentIds)
    6. End Sub
    Zum Db-Design:
    Mir gefällt das garnet, dass deine ShipmentId Datentyp String hat - und PONo auch - wieso sind das keine Ints?