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.

    Bitte um Kontrolle meines DataSets

    Hallo ihr lieben
    Ich habe jetzt das DataSet für mein Bestellrporamm fertig. (glaube ich)
    Das DataSet soll eine unbestestimmte Menge Artikel speichern (DataTable "Aricle).
    Außerdem sollen zu jedem Artikel alte Bestellungen und Bestände gespeichert werden können (DataTables "Date" und "DistributionTable" zur Zuordnung).
    Also ich habe eine aktuelle Bestellung (Row "Amount" in Table "Aricle"). Wenn ich diese Bestellung abschließe, soll sie mit entsprechendem Datum gespeichert werden.
    Wenn man sich das ganze tabellarisch vorstellt soll da so aussehen:

    Name
    18.02.1905.01.19Bestand 25.12.18
    Artikel1Infos / Preis / Ve, ets (in eigenen Spalten)5
    1
    Artikel2Infos
    21

    Die gespeicherten Daten können dabei Bestellungen, oder Bestände sein. (dafür die rows "IsOrder" und "IsStock" in der DistributionTable).

    Ist mein DataSet so in Ordnung, oder kann ich das irgendwie anders gestalten? Irgendwie hab ich im Gefühl, dass das einfacher gehen würde.

    Ist es möglich, die Daten aus meinem DataSet per Designer wie in meiner Tabelle oben darzustellen? Oder klappt das nur mit Code?

    *Topic verschoben*
    Bilder
    • DataSet.jpg

      197,03 kB, 1.600×900, 180 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Ich würd mein Veto dagegen einlegen, dass Du Inventur-Bestände und Bestellmengen in einen Topf eine DataTable haust. Zwei Booleans bieten immer vier Möglichkeiten. Aber nur 2 Kombinationen ergeben bei Deinem Datenmodell Sinn (True/False oder False/True). Daher ist die Tabelle so nicht richtig. Sie sollte zweigeteilt werden. Eine Tabelle mit Orders (also Bestellungen) und eine Tabelle mit Stocktaking (Inventur). Denn Amount hätte ja auch eine doppelte Bedeutung: Bestellmenge oder Bestand. Sowas in einer Tabelle zusammenzufassen sehe ich als unsauber an, weil Du dann über die Boolean-Werte auch bei Datenauswertungen Deine Bestellungen von Deiner Inventur trennen müsstest.
    Bzgl. DateTable gebe ich meinem Vorschreiber recht: Ein Datum in eine einzelne Tabelle zu schreiben, ist Overkill. Dann soll doch die Inventurtabelle oder die Bestelltabelle wissen, wann die entsprechenden Bestände so waren bzw. wann wieviel bestellt wurde. Und zwar durch eine Date-Spalte, nicht durch einen Verweis in einer weiteren Tabelle.
    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.
    Danke euch beiden :o)
    Dass 2 booleans vier Möglichkeiten ergeben leuchtet mir ein.
    Die Trennung von Inventur und Bestellung verstehe ich noch nicht ganz.
    Ich könnte dich die Boolean IsStock entfernen und nur IsOrder verwenden (True = Bestellung / False = Inventur).

    Ich habe mal ein Bild gemalt - wie ich mir die fertige Datei vorstelle (vielleicht spielt das ja in die DataSet Überlegung mit rein).
    Das DGV soll dabei so aussehen, wie die Tabelle aus letztem Post. Hier sollen neben den Artikeln eine Spalte für jedes Datum auftauchen (egal ob Inventur, oder Bestellung).
    DIe entsprechenden Mengen sollen dann angezeigt werden. Wenn es sich um Inventur handelt, wollte ich die Spalte grau färben.
    Allerdings ist "Inventur" nur bedingt korrekt. Ich zähle den Bestand bei manchen Firmen, um die Bestellungen zu vereinfachen. Also z.B. um immer auf die gleiche Menge aufzustocken (10 Stück da - also 10 Bestellen, weil ich immer 20 da habe).

    Um das mit dem DGV zu realisieren, dachte ich mir "lagere" ich mir die Datumswerte aus. Damit ich aus dieser Table die entsprechenden Datumswerte pulen kann.
    Dann kann ich über die Fremdschlüsselspalten Mengen und Artikel zu diesem Datum zuordnen und anzeigen.
    Und mit meiner Boolean "IsOrder" könnte ich dann entsprechend die Spalte grau färben, oder nicht.

    Ist das so nicht einfacher, als wenn ich die Datumswerte direkt in die DistributionTable schreibe?
    Und dann noch 2 Tables mit Mengen (Inventur und Bestellungen) habe, die ich im Code nach Datum sortiert anzeigen will?
    Oder habe ich hier einen Denkfehler?
    Bilder
    • 123.jpg

      599,01 kB, 2.500×1.667, 159 mal angesehen
    die in post#1 gezeigte Tabelle ist eine Kreuz-Tabelle - sowas kann DGV mit Databinding nicht.
    Und ohne Databinding auch nur mit sehr hohem Aufwand.
    Alternativ und sehr einfach könntest du einen Parent-Child-View aufbauen: Links die Artikel, und rechts die Distributions des angewählten Artikels.
    Sieht natürlich nicht so schick aus.
    Kann dafür aber auch über 30 Datumse anzeigen, was bei einer Kreuztabelle gewaltig in die Breite gehen würde.
    Und v.a. schnell gemacht und funzt sicher.
    Was man von einer selbstgebastelten Kreuztabelle weder in dieser noch in jener Hinsicht behaupten kann.
    Hmm. Ich glaube, ich möchte meine Kreuztabelle nur haben, weil ich seid vielen Jahren mit Excel arbeite. Bin Tabellen gewöhnt :o)
    Allerdings interessieren mich ja eh nur die Bestellungen zu dem einen ausgewählten Artikel. Also kann ich mir die Tabelle auch sparen... Weg damit.

    Also ändere ich mein DataSet so wie oben von @vb_fan , bzw. @VaporiZed empfohlen (DataTable weg, und datum in die Distribution rein - und aus der einen Distribution mache ich eine TableInventur und eine TableBestellungen)

    Dann werde ich meine Form 4 - teilen.
    oben links ein gebundenes DGV an die ArticleTable
    unten links eine DGV, in dem ich über eine Textbox die gefilterte ArticleTableindingSource anzeigen kann ("Cola" in die Textbox zeigt alle Artikel mit Cola im Namen).
    oben rechts die lezten Bestellungen und ggf. Inventurdaten des ausgewählten Artikels.
    unten rechts dann die Buttons (0-9), zum ändern der aktuellen Bestellmenge.

    Oder würdet ihr so eine Bestelldatei anders aufbauen? Ich finde leider keine fertige Software, die so etwas macht (kann nirgendwo Ideen klauen :o)
    und von mir selbst kommt leider nicht so viel - weil ich scheinbar in meiner Tabellewnelt gefangen bin.
    Ähm - in meiner Welt hat eine Bestellung meist mehrere Bestellposten.
    Es ergibt sich folglich eine m:n-Relation:
    Artikel->BestellPosten<-Bestellung

    Hier habich im Download eine wirklich schnucklige Beispiel-Anwendung zum Thema zusammengekloppt - gut geeignet, um dort Ideen zu klauen:
    codeproject.com/Articles/10351…set-for-Beginners#Explore the typed Dataset
    Sorry für folgenden "Sinnlospost".
    Allerdings finde ich es irgendwie unhöflich auf die geniale Hilfe hier nicht zu reagieren.
    Vielen Dank @ErfinderDesRades für den Link.
    Diesen habe ich bisher nur grob überflogen, da mir tagsüber die Zeit - und abends dann die Lust - fehlt, mich intensiv, mit etwas zu befassen.
    Nach 11 Stunden laden (mit aktuell 4 fehlenden Leuten) und wenn dann alles so halbwegs fertig ist, will ich nur noch Glotze an / Gehirn aus.

    Also eine "echte" Reaktion (also die nächsten Fragen) kommt denke ich nächste Woche.
    Holladiho.
    Soho - aus deinem Projekt kann ich so einiges auf mein Vorhaben anwenden :o)
    Auch der ObjektBrowser Exkurs ist enorm hilfreich (du solltest echt mal überlegen deinen Youtube Channel mit neuen Videos zu bespeisen :o)
    Ich werde mein Programm nun also sehr ähnlich deinem Projekt aufbauen (nur brauche ich keine Category Row und keine Customer Row) und ein paar andere Funktionen - die bei dir nicht sind.
    Ich kann nun bereits eine neue Bestellung anlegen und auch meiner Bestellung Artikel hinzufügen.
    Jedoch habe ich hierzu eine Frage. Denn du schreibst auf CodeProjekt:
    In Code you will never-ever need to access any ForeignKey - if you do so, you do something wrong. It's wrong, because it's always easier to use the ParentRow itself, instead of a Foreign-Key (wich at least is nothing but a stupid number).

    Ich habe aber keine Ahnung, wie ich das auf meinen Code umsetzten soll (und habe auch bisher immer die ID benutzt - keine Ahnung, waurm das schlecht ist):
    Edit: Die orderRow ist eine Klassenweit gültig. In der Mainform-->Buttonklick neue Bestellung Prozedur, wird eine neue Orderrow erzeugt und an die sich öffnende Form übergeben.

    VB.NET-Quellcode

    1. Private Sub BTNSave_Click(sender As Object, e As EventArgs) Handles BTNSave.Click
    2. 'Prüfen ob Artikel ausgewählt ist
    3. If ArticleBindingSource.Current Is Nothing Then Exit Sub
    4. Dim SelectedArticle = DirectCast(DirectCast(ArticleBindingSource.Current, DataRowView).Row, DtsSettings.ArticleRow)
    5. 'neue Bestellposition anlegen
    6. Dim newOrderEntry As DtsSettings.OrderEntryRow
    7. newOrderEntry = DtsSettings.OrderEntry.NewOrderEntryRow()
    8. newOrderEntry.OrderID = OrderRow.ID 'wie ohne ID?
    9. newOrderEntry.ArticleID = SelectedArticle.ID
    10. newOrderEntry.Amount = TBAmount.Text 'string, um z.B. 5+1 bestellen zu können
    11. newOrderEntry.Price = Decimal.Parse((Double.Parse(TBAmount.Text) * SelectedArticle.Ve).ToString) 'hier kommt ne Funktion (wegen 5+1)
    12. DtsSettings.OrderEntry.Rows.Add(newOrderEntry)
    13. End Sub


    Das Ergebnis sieht glaube ich gut aus:

    XML-Quellcode

    1. <?xml version="1.0" standalone="yes"?>
    2. <DtsSettings xmlns="http://tempuri.org/DtsSettings.xsd">
    3. <Article>
    4. <ID>-4</ID>
    5. <ArtNr>789</ArtNr>
    6. <EAN>2</EAN>
    7. <Name1>neu</Name1>
    8. <Name2>name2</Name2>
    9. <Ve>5</Ve>
    10. <PurchasingPrice>15</PurchasingPrice>
    11. <Tax>7</Tax>
    12. </Article>
    13. <Article>
    14. <ID>-5</ID>
    15. <ArtNr>111</ArtNr>
    16. <EAN>123</EAN>
    17. <Name1>test</Name1>
    18. <Ve>52</Ve>
    19. <PurchasingPrice>15</PurchasingPrice>
    20. <Tax>19</Tax>
    21. </Article>
    22. <Order>
    23. <ID>-11</ID>
    24. <OrderDate>2020-02-09T16:13:31.832597+01:00</OrderDate>
    25. </Order>
    26. <OrderEntry>
    27. <ID>-2</ID>
    28. <OrderID>-11</OrderID>
    29. <ArticleID>-4</ArticleID>
    30. <Amount>5</Amount>
    31. <Price>25</Price>
    32. </OrderEntry>
    33. </DtsSettings>
    Das Gesums zwischen Z#6 und #11 kann so geschrieben werden:

    VB.NET-Quellcode

    1. DtsSettings.OrderEntry.AddOrderEntryRow(ParameterInBestimmterReihenfolge) '*
    Bei der Reihenfolge hilft Dir IntelliSense. Und da zeigt sich auch, dass IntelliSense (bzw. natürlich die AddOrderEntryRow-Funktion keine OrderID oder ArticleID will, sondern die entsprechenden Rows.

    * der tDS-Codegenerator erzeugt zu jeder Tabelle eine entsprechende Funktion: TabellenName.AddTabellenNameRow(Parameter), also z.B. für die Tabelle Cars eine AddCarsRow, für People eine AddPeopleRow
    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.
    Top!

    VB.NET-Quellcode

    1. Private Sub BTNSave_Click(sender As Object, e As EventArgs) Handles BTNSave.Click
    2. 'Prüfen ob Artikel ausgewählt ist
    3. If ArticleBindingSource.Current Is Nothing Then Exit Sub
    4. Dim SelectedArticle = DirectCast(DirectCast(ArticleBindingSource.Current, DataRowView).Row, DtsSettings.ArticleRow)
    5. 'neue Bestellposition anlegen
    6. Dim Price = Decimal.Parse((Double.Parse(TBAmount.Text) * SelectedArticle.Ve).ToString)
    7. DtsSettings.OrderEntry.AddOrderEntryRow(OrderRow, SelectedArticle, TBAmount.Text, Price)
    8. End Sub

    Wenn ich einen Wert leer lassen möchte - sagen wir den letzten Parameter "Price" - schreibe ich nothing rein?
    ​DtsSettings.OrderEntry.AddOrderEntryRow(OrderRow, SelectedArticle, TBAmount.Text, nothing)
    Ja, oder einfach (0), also Null. Kommt natürlich drauf an, was es bedeuten soll. Ein Artikel, bei dem Du den Preis noch nicht kennst oder nicht festlegen 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.
    jo - ich bezweifel auch das Datenmodell.
    In meiner Welt gibt es keine Artikel ohne Preis.
    Und auf der anneren Seite auch keinen OrderEntry mit Preis.
    Der Preis einer Bestellung ergibt sich aus den bestellten Artikeln.

    Es sei denn, die Preise sind nix fixes, sondern werden jedesmal neu ausgehandelt - ungewöhnlich fände ich das.
    Ja, bleibt nicht zu sehr bei dem Beispiel.
    Auch in meiner Welt gibt es keinen Artikel ohne Preis.
    Aber es wird sicherlich irgendwann mal vorkommen, dass ich eine DataRow anlege in der ein Wert unbekannt, oder eben null ist.
    Da ich ja jeden Parameter der AddRow Funktion angeben muss, muss ich ja wissen, was dann ist.

    Edit:
    Ich habe gestern Abend eine - nennen wir es RawView Version - meines Bestellprogrammes fertiggestellt.
    Die Importfunktion (also Artikel aus dem Hauptprogramm ins Bestellprogramm) klappt hervorragend. Es gibt hierfür 3 Startmöglichkeiten für das Programm.
    2 aus dem Hauptprogramm (mit und ohne Import). In beiden Fällen wird die Firma übergeben und im Bestellprogramm das entsprechende DataSet geladen, bzw. in das DataSet Importiert.
    Außerdem kann die exe des Bestellprogrammes gestartet werden. Passiert dies, kann der User die Firma auswählen anhand der xml Dateien im Programmordner.
    Sinn und Zweck hiervon ist ein Bestellvorgang auf einem anderen PC. Ich kopiere Programm und xml von Firma1 auf diesen PC und kann an meinem Rechner gleichzeitig eine andere Bestellung tätigen.

    Der Rest ist dann - wie gesagt sehr Raw - eine Möglichkeit das Bestellprogramm aufzubauen.
    Könntet ihr hier mal rüberschauen und mir sagen, ob die Reise in die richtige Richtung geht - oder ob ich Dinge programmiert habe, die kurz- oder langfristig, totaler Murks sind.
    Dateien

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

    ErfinderDesRades schrieb:

    Es sei denn, die Preise sind nix fixes, sondern werden jedesmal neu ausgehandelt - ungewöhnlich fände ich das
    So ungewöhnlich fände ich das nicht.
    Vielleicht werden sie nicht jedesmal ausgehandelt, aber Preise sind üblicherweise Änderungen unterworfen.
    Ich würde sogar darüber nachdenken, Artikelpreise mit Gültigkeitszeitraum zu versehen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    DerSmurf schrieb:

    Ja, bleibt nicht zu sehr bei dem Beispiel.

    Ich fände es schon sehr ungewöhnlich, auch wenn ich Preise bei jeder Bestellung neu verhandel, wenn ich zum Zeitpunkt der Bestellung den Preis nicht kenne...
    Preise werden ja durch den Import außerdem automatisch kontrolliert und ggf geändert.
    Aber wie gesagt, das hier mit dem Preis war nur ein (ziemlich doofes) Beispiel, es geht nur darum wie ich einen Wert leer lasse (nicht welchen und warum)
    So, ich werde es nun doch mit Kategorien machen. Dazu habe ich aber eine Frage.
    Zum testen habe ich ein primitives DataSet gebaut. Eine Table Kategorien und eine Table Artikel. Jeder Artikel ist einer Kategorie zugeordnet.
    Nun habe ich das DGV der Kategorien auf die Form gezogen, und das hierin eingeschachtelte DGV der Artikel.
    Wenn ich nun eine Kategorie auswähle, werden mir im ArtikelDGV nur Artikel dieser Warengruppe angezeigt.
    Wie bewerkstellige ich es, dass im gleichen ArtikelDGV alle Artikel (also unabhängig von der Warengruppe) angezeigt werden?
    Habe mal ein Bild des DataSets, sowie eine kleine Beispielanwendung hochgeladen.
    Ziel ist es, dass die Ausgabe der Artikel im DGV oben rechts, genauso aussieht, wie im ArtikelDGV unten (alle Artikel)
    Bilder
    • Unbenannt.jpg

      219,99 kB, 1.920×1.080, 117 mal angesehen
    Dateien
    • WaregroupTest.zip

      (302,34 kB, 116 mal heruntergeladen, zuletzt: )
    Gar nicht. Was soll das auch? Entweder du willst eine kategorisierte/warengruppenabhängige Anzeige oder eben nicht. Wenn Du das umsetzen willst, müsstest Du m.E. ein DGV wie unten hernehmen und sagen, dass Du ggf. dort nur Artikel einer Warengruppe anzeigen lassen willst. Aber das geht dann eben nur mit Filtercode. Aber einer "vorgefilterten BindingSource" den Vorfilter zu entfernen, ist Pfeil-Rücken-Brust-Auge.
    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.
    Ich möchte mit einer Textbox die ArticleBindingSource durchsuchen und filtern.
    "Cola" als Suchbegriff, soll mir alle Colas anzeigen.
    Ein gesuchter EAN Code soll mir den entsprechenden Artikel liefern.
    Egal in welcher Kategorie er sich befindet.
    Außerdem gibt es Situationen, in denen ich gerne alle Artikel (egal welche Kategorie) alphabetisch sortiert anzeigen möchte.

    Lege ich dann ein KategoryDGV und ein nicht eingeschachteltes ArticelDGV auf die Form und bastel mir meine Filterung in einem KategoryDGV_Click Event, oder in der KategoryBindingSourcechangeCurrent Event selber?
    Oder lege ich an die gleiche Stelle zwei ArticelDGV (mit zwei unterschiedlichen BindingSources - einmal in Kategory geschachtelt - einmal normal) und lasse mir nur entsprechend der auswahl (KAtegory, oder alle) die DGVs anzeigen?