Bitte um Kontrolle meines DataSets

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

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    Ich würd es so machen: Ein DGV, in dem erstmal alle Artikel aufgelistet werden, also kategorieunabhängig. Dann ne Suchtextbox, deren Inhalt beim Drücken der Entertaste ausgewertet wird. Das hätte auch den Vorteil, dass Du Barcodes abscannen kannst, da die mir bekannten Scanner per Default ein Enter als letztes Zeichen schicken. Dadurch hast Du die Möglichkeit, einen Artikel zu finden, dem der abgescannte Barcode zugeordnet ist aber auch Teilsuchbegriffe zu verwenden, d.h. z.B. gibst Du Cola ein und das Programm sucht alle Artikel, die mit Cola beginnen oder Cola als Wortbestandteil beinhalten. Das musst Du selber festlegen, wie Du da suchen lassen willst.
    Dann ein KategorieDGV, bei dem Du beim Anklicken einer Kategorie alle Artikel einer Kategorie in der Artikelliste angezeigt bekommst, indem Du per LINQ die passenden Artikel auflisten lässt.
    Das Zurückkehren zur kompletten Artikelliste kannst Du entweder durch einen Filter-löschen-Button bewerkstelligen oder indem Du in der Textbox nichts eingibst und Enter drückst. Da kommt es natürlich auch drauf an, ob Du den Kategoriefilter mit dem Textboxfilter kombinieren willst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hmm. Hier habe ich ein Verständnissproblem.
    Linq gibt mir doch nur eine Kopie der Daten wieder. Nachdem ich also meine Artikel nach Kategorie mittels Linq anzeigen lasse, arbeite ich doch nicht weiter mit den Originaldaten, sondern mit einer Kopie der Daten weiter.
    Wie kann ich denn dann Änderungen in meinem DataSet speichern? Oder hab ich hier was falsch verstanden?
    Und wie bekomme ich eine mit Linq gefilterte Liste in mein DGV?
    Meine Lösung sieht bisher (ohne Linq) wie folgt aus:

    VB.NET-Quellcode

    1. Private CategoryChange as boolean = False
    2. Private Sub CategoryBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles CategoryBindingSource.CurrentChanged
    3. If CategoryChange Then
    4. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    5. ArticleBindingSource.Filter = "CategoryID = " & SelectedCategory.ID
    6. End If
    7. End Sub
    8. Private Sub CategoryDataGridView_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles CategoryDataGridView.DataBindingComplete
    9. CategoryChange = True
    10. End Sub


    Die Variable CategoryChange dient dazu, das triggern meiner BindingSource_CurrentChange Methode zu verbieten, wenn die Form geladen wird.
    Doof hier ist natürlich, dass ich die Filter Methode statt Linq verwende und ich möchte eigentlich Kategorien und Suchen Textbox unabhängig voneinander haben.
    Also wenn ich den Filter der Suchen Textbox lösche, soll der Kategorie Filter erhalten bleiben. Zum anzeigen alle Artikel, werde ich entweder einen Eintrag in meine Kategorieliste "alle" erstellen, oder eben einen Button.
    Jedoch kann ich doch nicht mehr als einen Filter für eine BindingSource festlegen, oder doch?

    Edit: Also meine Linq Abfrage müsste ja irgendwie so aussehen:

    VB.NET-Quellcode

    1. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    2. Dim RelevantArticle = DtsSettings.Article.Where(Function(x) x.CategoryID = Selectedcategory.id)

    Aber wie jetzt die RelevantArticle im DGV anzeigen?
    Ich habe das hier versucht: ArticleBindingSource.DataSource = RelevantArticle.ToList() - allerdings bekomme ich einen Fehler für jede Spalte die DBNull ist. Es werden jedoch die richtigen Artikel angeizegt.

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

    DerSmurf schrieb:

    Linq gibt mir doch nur eine Kopie der Daten wieder.
    Nicht immer. Linq kann - unter Beachtung bestimmter Regeln - ein gefiltertes DataView erzeugen.
    DataView bedeutet immer, dass es die Original-Daten sind, die behandelt werden.

    Also kommts drauf an, wie "dein" Linq in diesem Falle aussieht.

    Beim gezeigten Code versteh ich nicht die Frage. Mir sieht das gut funktionierend aus. Da würde ich keine Linq-Experimente unternehmen.
    Die Linq-Dataviews haben nämlich den Nachteil, dass deren Sort- und Filter- Property Bockmist baut.

    Achso - um dein Linq in Funktion zu bringen, probierma:

    VB.NET-Quellcode

    1. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    2. Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.Category Is Selectedcategory) ' schon vergessen? beim Programmieren gegen ein typDataset braucht man die IDs nicht
    3. dgv.DataSource = RelevantArticles.AsDataView

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

    Huhu!

    ErfinderDesRades schrieb:

    ' schon vergessen? beim Programmieren gegen ein typDataset braucht man die IDs nicht

    Nein. Nicht vergessen. Aber gekonnt ignoriert, so wie es mir auch immer mit Option Infer, oder diesem "x +=1" geht. Aber ich arbeite an mir :o)

    Deine Linq Lösung funktioniert bei mir - es werden die korrekten Artikel, ohne Fehlermeldung angegeben.
    Jedoch habe ich auch hier wieder den Umweg über die ID eingeschlagen, denn ​'Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.CategoryID Is SelectedCategory) erzeugt den Fehler:
    '"Category" ist kein Member von "DtsSettings.ArticleRow" (ich habe allerdings die normale "Article-Datenquelle auf die Form gezogen - nicht die in der Category eingeschachtelte - vielleicht liegts daran?)
    Wie gesagt der Rest funktioniert dann auch mit Linq.
    Wenn du aber sagst, dass Filter und Sortierfunktion dieser Linq Ausgabe dann Buggy sind, bleibe ich ja lieber bei meiner Filter Methode.
    Trotzdem interessiert mich natürlich, wie ich die Artikel (ohne Verwendung der ID) mittels Linq filtern kann.

    Und dann stellt sich natürlich die Frage, wie ich mehrere Filter auf eine Binding Source anwende, bzw. nur einen von mehreren Filtern eine BindingSource entferne.
    Also z.B. Filter 1 = Kategory "Getränke"
    Filter 2 = TBSearch.Text = "Cola"

    Nun werden mir in der Kategory Getränke alle Artikel mit "Cola" im Namen angezeigt.
    Ich möchte nun z.B. Filter 2 löschen, Filter 1 soll aber bleiben. Also alle Getränke sollen angezeigt werden





    VB.NET-Quellcode

    1. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    2. 'Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.CategoryID Is SelectedCategory)
    3. Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.CategoryID = SelectedCategory.ID)
    4. ArticleDataGridView.DataSource = RelevantArticles.AsDataView

    VB.NET-Quellcode

    1. Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.CategoryID Is SelectedCategory)
    Das ist nicht von mir - das ist von dir.
    (und natürlich kriegt das nen Fehler, weil eine CategoryId ist natürlich keine Category)

    Bei mir hiess es:

    VB.NET-Quellcode

    1. Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.Category Is SelectedCategory)
    Wenn das ein Fehler gibt, dann hast du versäumt, eine Relation im typDataset einzurichten, oder gar in der Datenbank, wo der Kram herrührt.
    (Oder dein Datenmodell ist noch anders als ich mir vorstell)
    Sorry! Nachdem ich deinen Code einkopiert habe, kam es zum Fehler: "Category ist kein Member von DtsSettings.ArticleRow", deswegen habe ich ein bisschen rumprobiert.
    Also nochmal. Folgender Code funktioniert nicht:

    VB.NET-Quellcode

    1. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    2. Dim RelevantArticles = DtsSettings.Article.Where(Function(x) x.Category Is SelectedCategory)
    3. ArticleDataGridView.DataSource = RelevantArticles.AsDataView

    Auch wenn - wie du ja selber sagst - meine Lösung mit BindingSource.Filter für das Problem hier sinnvoller ist, fände ich es schön, wenn wir uns auf Fehlersuche begeben könnten. Denn unter Umständen habe ich einen Fehler in meinem Datenmodell - das find ich ganz schön doof.

    ErfinderDesRades schrieb:

    Wenn das ein Fehler gibt, dann hast du versäumt, eine Relation im typDataset einzurichten, oder gar in der Datenbank, wo der Kram herrührt.

    Soweit ich das beurteilen kann, ist mein DataSet in Ordnung. Zur Sicherheit habe ich mal ein Screenshot angehängt.
    Die Daten sind nach einem Import im angehängten DataSet (als xml) gespeichert.
    Der Import aus meinem Hauptprogramm läuft folgendermaßen: (Abkürzung HP für Hauptprogramm, BP für das aktuelle Programm hier)
    1. Durchsuchen der Artikel aus HP nach bestimmten Lieferanten und speichern in DtsExport.Article und schreiben des gesamten DtsExport (welches nur diese eine Table besitzt) in xml
    2. Schreiben von CategoryTable aus DtsSettings in xml
    3. wenn BP mit Parameter IMPORT gestartet wird, einlesen der xml Category in DtsSettings.Category und lesen von xml-DtsExport.Article (aus HP) in BP.DtsExport.Article
    4. in BP Artikel aus DtsExport.Article durchgehen (For each) und Artikel zu DtsSettings.Article hinzufügen, wenn noch nicht vorhanden (Kontrolle anhand von Article.ArtNo)
    5. Außerdem werden noch Artikel in DtsSettings.Article bearbeitet, falls ein Artikel mit gleicher Artikelnummer in DtsExport einen anderen Preis z.B. hat - wird dieser in DtsSettings übernommen.
    Bei all dem Importgedöns (ich hoffe ich habs verständlich erklärt), gibt es nirgendwo eine Relation (weil ja Dts.Export nur eine Table für Artikel hat). Die Relation hat dann nur das endgültige DataSet DtsSettings.
    Aber das sollte doch eigentlich egal sein, oder?

    Edit: Ich habe auch mal das DtsSettings meine Hauptprogrammes angehängt.


    Soweit ich das beurteilen kann ist aber mein Datenmodell in Ordnung. Ich habe mal einen Screenshot angehängt.

    Edit: Ich habe noch eine Frage zum DataSet.
    Wenn Artikel in das Programm import werden, lade ich beide DataSets (DtsExport und DtsSettings) eigentlich müsste ich bei DtsSettings nur die Table "Article" laden. Jedoch scheitert dies, sobald ich eine Bestellung gespeichert habe (Order und OrderEntry) an den Beziehungen, deswegen lade ich das komplette DtsSettings.
    Nun möchte ich aber DtsSettings.Category löschen und aus einer xml neu einlesen.

    VB.NET-Quellcode

    1. Me.DtsSettings.ReadXml(xmlFile)
    2. Me.DtsSettings.Category.Clear()
    3. Me.DtsSettings.ReadXml(TempCategory)

    Ich kann jedoch DtsSettings.Category.Clear nicht ausführen, wegen des Fremdschlüssels auf DtsSettings.Article.
    Kann ich das irgdendwie umgehen?

    Ich habe in der MSDN folgendes gefunden:

    VB.NET-Quellcode

    1. dataSet1.EnforceConstraints = false
    2. // Perform some operations on the dataset
    3. dataSet1.EnforceConstraints = true

    kann ich das bedenkenlos verwenden, wenn sichergestellt ist, dass nach dem Import der Daten, alle Beziehungsbedingungen wieder erfüllt sind?

    Also Einschränkung aus. Kategorien löschen - Kategorien aus xml neu laden und Einschränkungen wieder ein.
    Dann könnte ich ggf. noch eine Funktion einbauen, die jede ArticleRow prüft, ob die ID auf Fremdschlüssel Category existiert und ggf. ändert.
    Bilder
    • DtsExport.jpg

      209,84 kB, 1.920×1.080, 48 mal angesehen
    • DtsSettings.jpg

      286,11 kB, 1.920×1.080, 49 mal angesehen
    • DtsSettingsHauptprogramm.jpg

      344,97 kB, 1.920×1.080, 51 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DerSmurf“ ()

    Tja - ist mir unerklärlich.
    Wenn ich so ein Dataset bauen würde wie dein DtsSettings, dann würde der von mir angegebene Code auch funktionieren.
    War jedenfalls bislang so. Ausnahmslos.

    Übrigens noch eine Vereinfachung zum Auffinden aller Artikel:

    VB.NET-Quellcode

    1. Dim SelectedCategory = DirectCast(DirectCast(CategoryBindingSource.Current, DataRowView).Row, DtsSettings.CategoryRow)
    2. Dim RelevantArticles = SelectedCategory.GetArticleRows