Dataset Query für Many-To-Many Relation

  • VB.NET

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

    Dataset Query für Many-To-Many Relation

    Hallo!

    Ich hätte eine Frage bzgl. eines Queries eines DataSets. Ich kann einen direkten Query auf ein DataSet anwendenden
    bekomme aber die Denke für eine Many-To-Many Relation nicht hin... :wacko:

    Ich habe ein DataSet das folgendermaßen aussieht:

    --- Model ---
    |ID
    |Name
    -------------
    |
    |
    --- ModelTag ----
    |mdlID
    |tagID
    -----------------
    |
    |
    --- Tag ---
    |ID
    |Name
    -----------

    Ich habe eine Junction Tabelle für Tags erstellt, die jedes Model haben kann.
    Einen Direkten, also 1:n, Query bekomme ich hin:

    VB Express 2010:

    VB.NET-Quellcode

    1. Dim mdls As DataTable = DbDataSet.Tables("Model")
    2. Dim query = _
    3. From m In mdls.AsEnumerable() _
    4. Where m.Field(Of Int32)("catID") = 1 _
    5. Order By m.Field(Of String)("Name") Descending _
    6. Select m
    7. ModelDataGridView.DataSource = query.AsDataView()


    Aber wie sieht das bei einem Junction Table aus? Habe etwas von JOIN gelesen aber das hat
    nicht so geklappt, wie es sollte.

    Ich möchte bspw. alle Modelle haben, die einen oder mehrere bestimmte Tags
    haben oder andersherum

    Vielen Dank für eure Hilfe!
    wenn du mit typisiertem Dataset arbeitest, sollte die Query ganz anners aussehen - eben typisiert.

    Aber für die Anzeige im DGV wurstelt man besser überhaupt nicht mit Linq-Queries herum, denn dafür kann man die DGVs schlecht designen.
    Ausserdem kann man solchen Queries nix zufügen oder daraus Datensätze löschen.

    Gugge besser vier Views-Videos
    Danke für Deine Antwort!

    Typisierte DataSets wären besser ... ehrlich gesagt war mir aber nicht klar, wie ich
    die erstelle. Bis jetzt hat so alles für mich hingehauen, deshalb ist das noch so. Aber das ist ja ein
    anderes Thema... oder?


    Wie erstelle ich den gewünschten Query in diesem bestimmten Fall (also mit Strings für die Zugriffe)?

    Danke! :)

    asury schrieb:

    Aber das ist ja ein anderes Thema... oder?
    ja und nein.
    eng gesehen ja, weil es ist halt ein anderes Thema.
    bisserl grundsätzlicher gesehen nein, es ist dasselbe Thema: nämlich, wie du verknüpfte Datensätze in einem DGV anzeigst.
    Und da ist dein bisheriger Ansatz ein Holzweg, den du früher oder später eh verwerfen wirst - und früher wäre besser.
    Nimm dir die Zeit für den m:n - View auf vier Views-Videos - du musst dir diese Zeit sowieso nehmen, früher oder später.
    Vielen Dank!

    Ich verstehe! :)

    Ich werde mir die Tuts von Dir mal anschauen... die vier-views habe ich eigenltich schon angeschaut (super btw. :)). Die anderen führe ich mir
    dann auch mal zu Gemüte.

    Dann setzte ich mich mit typisierten DataSets mal auseiander.
    Ich befürchte aber, dass weitere Fragen folgen werden. ;)
    Was ich nämlich grundsätzlich machen möchte, ist einen DGV mit einer CheckedListBox (n:m relation) zu filtern. Also alle Tags anhaken und der
    DGV filtert mir dann alle Modelle raus, die diese Tags haben.
    Das wäre ein JoiningView mit Joins auf beide übergeordneten Tabellen.
    Und man würde einen komplexen Filter setzen müssen, also wo viele Teil-Bedingungen mit "OR" verknüpft sind.
    Könnte man auch mit Linq2Dataset lösen, aber die dabei entstehenden DataViews sind buggy (sie lösen sich in Luft auf, wenn sie sortiert werden).
    Ein komplexer Filter ist da stabiler.

    ErfinderDesRades schrieb:

    Das wäre ein JoiningView mit Joins auf beide übergeordneten Tabellen.
    Ich habe mir Deine Videos mit dem JoiningView nochmal angeschaut und leider
    bleibt es mir trotzalledem verborgen wie ich Joins auf beide Tabellen mache. Übersehe
    ich etwas grundlegendes?

    Etwas "Hausaufgaben" habe ich gemacht (funktioniert ganz wunderbar):

    VB.NET-Quellcode

    1. Dim model = DirectCast(detailItem, dbDataSet.ModelRow)
    2. txtMdlName.Text = model.Name
    3. Dim modelTags() As dbDataSet.ModelTagRow = model.GetModelTagRows()
    4. For Each modelTag As dbDataSet.ModelTagRow In modelTags
    5. Dim tag As dbDataSet.TagRow = modelTag.TagRow
    6. MsgBox(tag.Name)
    7. Next


    Ich habe jetzt einen DGV von Tags und ModellTags auf die Form gezogen:
    Beim auswählen eines Tags zeigt er mir brav alle zugehörigen Datensätze der
    Junction Tabelle an. Aber wie bekomme ich jetzt die Modelle, die zu dem
    Tag gehören? Die Werte der JunctionTable interesieren mich ja nicht wirklich, sondern
    mit was diese verknüpft sind. Wie "joine" ich jetzt in den DGV der ModelTags die
    Modelle? Ich möchte keine ComboBoxen zu den zugehörigen Modellen sondern pur die Modelle
    mit Modell-Eigenschaften darstellen ?( Ich bin leider etwas verwirrt, wie das zu
    bewerkstelligen ist, ohne einen expliziten Query zu machen... :(

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „asury“ ()

    asury schrieb:

    Beim auswählen eines Tags zeigt er mir brav alle zugehörigen Datensätze der
    Junction Tabelle an. Aber wie bekomme ich jetzt die Modelle, die zu dem
    Tag gehören?
    Tja - wie ist das denn im m:n-View im Tutorial gemacht?
    Da werden doch die Deliverer aller Artikel der ausgewählten Kategorie angezeigt, oder nicht?

    ErfinderDesRades schrieb:

    Da werden doch die Deliverer aller Artikel der ausgewählten Kategorie angezeigt, oder nicht?
    Jep... das ist korrekt. Aber dich interessieren ja "nur" die Daten auch in
    direkter Verbindung zum "Article" (JunctionTable) stehen. Ich möchte den JunctionTable
    überhaupt nicht sehen und effektiv überspringen! :)

    Hier nochmal unsere beiden DataSet-Schemata zum Vergleich:


    Du machst ja jeweils 2 Verbindungen in dem n:m Video
    1. Category -> Article
    2. Deliverer -> Article

    Ich möchte aber folgende Verbindung wobei ich die "Mitte" gar nicht sehen will:
    1 Tag -> ModelTag <- Model

    Wenn ich jetzt keinen totalen Denkfehler habe, dann interessieren Dich ja die Daten
    der Junction Tabelle (Article). Du zeigst dir jeweils den Artikelnamen und den Preis an.

    Ich habe die Junction Tabelle ja nur als Vermittler als Verweis auf die Modelle. Die Daten
    davon interessieren mich ja nur perifär.

    Please enlighten me! :S

    Als Ansatz habe ich im Netz folgendes Tutorial gefunden:
    blogs.msdn.com/b/bethmassi/arc…to-many-data-binding.aspx

    Folgender Code funktioniert "so halb" mit einem DGV zum filtern (müsste ich noch für die
    CheckedListBox umbauen):

    VB.NET-Quellcode

    1. Private Sub ModelTagBindingSource_ListChanged(ByVal sender As BindingSource, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles ModelTagBindingSource.ListChanged
    2. If sender.Count > 0 Then
    3. Dim filter As New System.Text.StringBuilder()
    4. For Each drv As DataRowView In CType(sender.List, DataView)
    5. Dim modelTag As dbDataSet.ModelTagRow = DirectCast(drv.Row, dbDataSet.ModelTagRow)
    6. If filter.Length <> 0 Then
    7. filter.Append(" OR ")
    8. End If
    9. filter.Append("ID=" & modelTag.mdlID)
    10. Next
    11. Me.ModelBindingSource.Filter = filter.ToString
    12. Else
    13. Me.ModelBindingSource.Filter = Nothing '"1 = 0"
    14. End If
    15. End Sub

    asury schrieb:

    Wenn ich jetzt keinen totalen Denkfehler habe, dann interessieren Dich ja die Daten
    der Junction Tabelle (Article). Du zeigst dir jeweils den Artikelnamen und den Preis an.
    Ähm - ich zeige aber doch auch den Lieferanten an, odr?
    Meine ArticleTable ist halt eine JunctionTable mit "Zugaben" (Name und Preis).
    Du brauchst die Zugaben ja nicht anzuzeigen - was siehste dann? Jawohl, nurnoch den Lieferanten eines Artikels - vom Artikel selbst siehste nixmeh :D

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

    ErfinderDesRades schrieb:

    Jawohl, den Lieferanten eines Artikels - vom Artikel selbst siehste nixmeh.
    Sorry, ich möchte Dir da nicht auf die Nerven gehen... aber:
    Wenn ich Preis und Name der JunctionTabele weglasse, sieht man genau ein Feld (Name) der Deliverer Tabelle in
    einer ComboBox... aber doch nicht alle Daten zu dem Deliverer, oder? Sagen wir mal der Deliverer hat noch 4 andere
    Felder die ich in der Liste sehen will... genau das will ich erreichen! :)

    ErfinderDesRades schrieb:

    übrigens, du nervst nicht - ich finde deine Fragen ganz sinnvoll.
    da bin ich beruhigt :)

    Habe das Problem jetzt so lösen können:

    VB.NET-Quellcode

    1. Private Sub chkLBTagsFilter_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkLBTagsFilter.SelectedIndexChanged
    2. Dim selTag As dbDataSet.TagRow = chkLBTagsFilter.SelectedItem.dataRow
    3. Dim filterTagModel As New System.Text.StringBuilder()
    4. For Each sel In chkLBTagsFilter.CheckedItems
    5. Dim tag As dbDataSet.TagRow = sel.dataRow
    6. If filterTagModel.Length <> 0 Then
    7. filterTagModel.Append(" OR ")
    8. End If
    9. filterTagModel.Append("tagID=" & tag.ID)
    10. Next
    11. Me.ModelTagBindingSource.Filter = filterTagModel.ToString
    12. If Not filterTagModel.ToString = "" Then
    13. Dim filterModel As New System.Text.StringBuilder()
    14. If ModelTagBindingSource.Count > 0 Then
    15. For Each drv As DataRowView In CType(ModelTagBindingSource.List, DataView)
    16. Dim modelTag As dbDataSet.ModelTagRow = DirectCast(drv.Row, dbDataSet.ModelTagRow)
    17. If filterModel.Length <> 0 Then
    18. filterModel.Append(" OR ")
    19. End If
    20. filterModel.Append("ID=" & modelTag.mdlID)
    21. Next
    22. Me.ModelBindingSource.Filter = filterModel.ToString
    23. Else
    24. Me.ModelBindingSource.Filter = Nothing
    25. End If
    26. Else
    27. Me.ModelBindingSource.Filter = Nothing
    28. End If
    29. End Sub


    Die CheckedItems sind meine eigenen Objekte, die eine DataRow für das angehakte
    Element enthalten.

    Danke nochmal für Deine Hilfe!

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

    Glückwunsch :thumbsup: - so ungefähr meinte ich!

    paar Details

    VB.NET-Quellcode

    1. Dim selTag As dbDataSet.TagRow = chkLBTagsFilter.SelectedItem.dataRow
    das scheint mir Strict Off programmiert. Wichtig: Option Strict On!

    VB.NET-Quellcode

    1. For Each drv As DataRowView In CType(ModelTagBindingSource.List, DataView)
    mach lieber direkt:

    VB.NET-Quellcode

    1. For Each drv As DataRowView In ModelTagBindingSource
    Casts sind leider oft unumgänglich, aber wenn umgänglich, sollte man sie umgängeln.

    Das hier kenne ich überhaupt nicht:

    VB.NET-Quellcode

    1. For Each sel In chkLBTagsFilter.CheckedItems
    2. Dim tag As dbDataSet.TagRow = sel.dataRow
    sel.dataRow? was ist sel fürn Datentyp?

    zum Layout auf VBP: Bitte VB-Tag benutzen - aber richtig

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