Datenmodell besser verstehen

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

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

    Datenmodell besser verstehen

    Hallo,

    also mit der FindByID Methode habe ich endlich meine Denkbarriere geknackt was das Verknüpfen von Daten angeht.

    Im DataSet-Designer kann man sich ja ein Datenmodell basteln, da habe ich aber nie verstanden wie man das machen muss. Aber codeseitig bekomme ich das jetzt ziemlich ordentlich hin.
    Vielleicht könnt ihr mir da die Parallelen nochmal aufzeigen?

    Also ich habe diese drei Tabellen als Grundlage. Ich hätte die Tabellen noch korrekt benennen sollen; DataTable1 = Produkte, DataTable2 = Bauteile, DataTable3 = Gruppen


    Im Code mache ich Folgendes:
    Also generell hat ein Produkt erstmal kein Datum. Ich füge einem Produkt das Datum seiner Gruppe hinzu.

    VB.NET-Quellcode

    1. For Each Produkt In DS1.DataTable1
    2. Produkt.Datum = DS1.DataTable3.FindByGroupID(Produkt.GroupID).Datum
    3. Next
    Ich denke DataTable1.GroupID ist also ein Fremdschlüssel für DataTable3?

    Dann suche ich noch raus ob dies oder jenes drinsteckt in einem Produkt. Das geht dann nur über die Bauteile.

    VB.NET-Quellcode

    1. For each Bauteil In DS1.DataTable2
    2. Dim check = DS1.DataTable1.FindByPaketIDProduktID(Bauteil.PaketID, Bauteil.ProduktID)
    3. If Bauteil.Typ = diesoderjenes1 Then check.DataColumn4 += 1 'oder so
    4. If Bauteil.Typ = diesoderjenes2 Then check.DataColumn5 = "Ja" 'oder so
    5. If ...
    6. Next
    Hier ist der Fremdschlüssel dann eigentlich der Primärschlüssel.

    Also im Designer kann ich mir darunter noch nicht wirklich was vorstellen, aber das war immer was ich erwartet habe was man eigentlich mit dem "richtigen" Datenmodell schon macht bzw. was man im Designer machen sollte.
    Oder bin ich da immer noch weit daneben?

    Viele Grüße

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

    Bevor EdR kommt und es Dir ausredet: Wir diskutieren immer wieder über die Frage, ob ein Tabellenname im Singular (Position von EdR und anderen) oder im Plural (Position von mir und anderen) gehalten werden soll. Keine Seite kann die andere endgültig überzeugen. Willkommen daher (vorerst?) auf der Pluralseite :P

    Die ID einer TabelleXYZ sollte nicht TabelleXYZID heißen, sondern schlicht und ergreifend ID.
    IrgendwasID wäre für mich immer ein Hinweis auf eine Fremd-ID.

    Haudruferzappeltnoch schrieb:

    Also generell hat ein Produkt erstmal kein Datum.
    Doch, da Date nicht Nothing sein kann. Es hat dann den Wert 01.01.0001. Es stellt sich daher erstmal die Frage, woher zu Beginn die Produktzeilen kommen, da Du bei deren Generierung ein Datum mit angeben musst.

    Haudruferzappeltnoch schrieb:

    Hier ist der Fremdschlüssel dann eigentlich der Primärschlüssel.

    Fremdschlüssel: Unique-Spaltenwert einer anderen Tabelle.
    Primärschlüssel: Unique-Spaltenwert einer Tabelle, der als primäres Identifikationsmerkmal hergenommen wird. Wenn Du 3 Unique-Spalten hast, musst Du Dir in Deinem Projektcode gedanklich selbst festlegen, was davon der Primärschlüssel ist.

    Was neben der ausbaufähigen Benennung der Tabellen aufällt: Dir fehlen die Verbindungen zwischen den Tabellen. Hier ein einfaches Gegenbeispiel:

    Der Pfeil, den man erstellen muss, führt dazu, dass der Compiler weiß, dass die Tabellen verknüpft sind. Vielleicht hast Du das schon, aber nicht mit im Bild. Wenn nicht, dann zeitnah nachholen.

    btw: Datum ist auch eine schlechte Benennung, nicht nur für eine Tabellenzeile. Was für ein Datum? Produktionsdatum, Auslieferungsdatum, Erfindungsdatum, Hochzeitstag (?)
    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.

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

    VaporiZed schrieb:

    Willkommen daher (vorerst?) auf der Pluralseite :P
    Hm, ich weiß wo das herkommt, die Tabellen sollen ja Objekte sein, deswegen Einzahl, aber für mich betrachte ich die Tabellen lieber als "Container"

    VaporiZed schrieb:

    Die ID einer TabelleXYZ sollte nicht TabelleXYZID heißen, sondern schlicht und ergreifend ID.
    Es ist aber keine Spalte für sich Unique in Tabelle 1 und 2, sondern nur Kombinationen davon. Also ID der Tabelle2 wäre quasi PaketID & ProduktID & BauteilID. Da kann ich nichts ID nennen.

    VaporiZed schrieb:

    Doch, da Date nicht Nothing sein kann. Es hat dann den Wert 01.01.0001. Es stellt sich daher erstmal die Frage, woher zu Beginn die Produktzeilen kommen, da Du bei deren Generierung ein Datum mit angeben musst.
    Ja die Datumsspalte hab ich DefaultValue = 01.01.1900 im Designer vergeben, die Tabellen werden alle per Fill gefüllt. Der SelectCommand für die Produkttabelle enthält kein Datum, das meinte ich.

    VaporiZed schrieb:

    btw: Datum ist auch eine schlechte Benennung, nicht nur für eine Tabellenzeile. Was für ein Datum?
    Genauer benannt habe ich es nicht, damit es simpel bleibt.

    VaporiZed schrieb:

    Dir fehlen die Verbindungen zwischen den Tabellen.
    Ja können diese Verbindungen meinen Code ersetzen? Das hab ich noch nicht verstanden. Die fehlen quasi bewusst, weil ich weder weiß wie noch wann die anzuwenden sind.

    Gebe ich den Fremdschlüssel denn noch gesondert an? Außer dass ich im Kopf weiß was der sein muss

    Haudruferzappeltnoch schrieb:

    für mich betrachte ich die Tabellen lieber als "Container"
    Sehe ich ganz genauso :D
    Bzgl. ID: Jede Tabelle sollte eine eigene ID-Spalte haben. Ob sie dann aktiv zum Einsatz kommt, sei dahingestellt. Aber ich hatte mal gelesen: Wer glaubt, keine zu brauchen, hat noch nicht lange genug programmiert. Irgendwann kommen sie einfach zum Einsatz. Vielleicht nicht bei jedem Projekt. Aber wenn man sie pro forma in jeder Tabelle drinhat, kann man sie später nicht vermissen, sondern immer darauf bauen, falls man sie doch mal braucht.
    Dass sie für Dich erstmal keinen praktischen inhaltlichen Nutzen haben, weil Du mit einer -5 als ID nix anfangen kannst, ist davon unberührt. Eine ProduktID, z.B. eine Seriennummer ist dann wieder was anderes. Die angesprochene ID ist nur für die DataTable/die DB/das Codeprojekt und hat nix mit dem realen Produkt zu tun.

    Die Verbindungen sind dafür da, damit eine übergeordnete Tabellezeile ihre zugeordneten Zeilen aus untergeordneten Tabellen kennt. Wenn es eine FirmenTabellenzeile gäbe und dazu 5 ProduktTabellenzeilen, die zu dieser Firma gehören, könnte man nur durch den tDS-Designer festlegen: Wird die Firma gelöscht, müssen auch die Produkte der Firma gelöscht werden. Welcher Firma sollten sie sonst gehören / zugeordnet sein? Ein Produkt ohne Hersteller ergäbe keinen Sinn. Demenstsprechend muss bei Erstellung einer Produktzeile auch immer angegeben werden, zu welcher Firma das Produkt gehört, wenn die Tabellen verknüpft sind.
    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.
    In den Tabellen werden nie einzelne Zeilen gelöscht oder hinzugefügt. Wie gesagt nur die Fill und Clear interagieren mit einem vollständigen Datensatz.

    Das heißt ich muss die Tabelle3 vor Tabelle1 laden wenn ich die Verknüpfung mache, sonst bekomme ich ja Gruppen, die es noch nicht in er Gruppentabelle existieren, weil die noch leer ist.
    Aber sei es drum, wenn ich Tabelle 3 und 1 über die GroupID verknüpfe, kann ich mir dann irgendwie das Übernehmen des Datums sparen?

    Ich füge es im Moment nämlich ein damit ich z.B. folgende Auswertung machen kann:

    VB.NET-Quellcode

    1. Dim erg as List(Of Ergebnis)
    2. For Each datum In Auswertungstage
    3. Dim q = From t In DS1.DataTable1 Where t.Datum = datum
    4. erg.Add(New Ergebnis With {.Datum = datum, .Stueck = q.Sum(Function(x) x.Stueck)})
    5. Next
    Die Tabellenladereihenfolge musst Du theoretisch einhalten, weil die automatische, tDS-interne Prüfung sonst meckern würde und eine ContraintException liefert. Die Prüfung kannst Du aber temporär (bitte nicht dauerhaft!) ausschalten: DeinTds.EnforceConstraints = False -> nach dem Datenladen wieder auf True schalten. Das aber nur, wenn Du eine Tabelle nach der anderen lädst. Würdest Du alles in einem Aufwasch laden, sollte es ohne gehen.

    Haudruferzappeltnoch schrieb:

    wenn ich Tabelle 3 und 1 über die GroupID verknüpfe, kann ich mir dann irgendwie das Übernehmen des Datums sparen?
    Nein, die Datenübernahme bleibt weiterhin Deine Aufgabe. Es gibt keinen Grund, warum das automatisch übernommen werden sollte. Ich weiß auch nicht, welche Logik bei Dir diesbezüglich dahintersteckt. Denn solange ich nicht weiß, was Datum inhaltlich bedeutet, erschließt sich mir auch nicht, warum das Datum eines Produkts von dessen Gruppe übernommen werden soll. Für Dich sicherlich absolut logisch. Aber kein Grund, warum es automatisch gehen soll. Das wäre sogar für mich ein Grund, diesen Codeteil in eine Methode auszulagern, deren Name genau beschreibt, was da passiert (und. ggf. warum).

    ##########

    Ach ja, Kleinigkeit: Irgendwas mach ich falsch. Ist es .NET-Framework 4.8? VS 2022? Bei mir werden immer noch keine FindBy…-Methoden generiert. Ich bekomm noch nen Vogel :cursing:

    ##########

    hat sich: Die FindBy…-Methode wird nur für Primärschlüsselspalten generiert. Notiz an mich: Um festzulegen, was der Primärschlüssel sein soll, Rechtsklick auf die gewünschte Tabellenspalte und auf Primärschlüssel festlegen klicken. Vergessenes Wissen :whistling:
    @Haudruferzappeltnoch: Entgegen meiner Post#2-Aussage kann man also auch dem Compiler mitteilen, was der Primärschlüssel ist. Aber das wusstest Du ja wahrscheinlich schon, wenn Du die FindBy…-Methoden nutzt.
    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.

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

    Haudruferzappeltnoch schrieb:

    Also ich habe diese drei Tabellen als Grundlage. Ich hätte die Tabellen noch korrekt benennen sollen; DataTable1 = Produkte, DataTable2 = Bauteile, DataTable3 = Gruppen
    Jo, dann tu das bitte.
    Es fällt unendlich viel einfacher von sinnvollen Dingen zu reden, wie Produkt, Bauteil, Gruppe.
    In deim Dataset sind keine Relationen angelegt - warum nicht?
    Es bestehen doch sicherlich Beziehungen zwischen Produkt, Bauteil und Gruppe.
    Diese solltest du uns erläutern, und dann sollen sich diese Beziehungen entsprechend deinen Erläuterungen im Datenmodell widerspiegeln.
    Du musst es erläutern, denn es gibt viele Möglichkeiten:
    Ein Produkt besteht vmtl. aus vielen Bauteilen.
    Aber ob eine Gruppe viele Produkte enthält, oder viele Bauteile, oder ob es sich noch anders verhält - das kannst nur du wissen.



    Zur Plural/Singular-Debatte - da haben wir ja schon einen schönen Einstieg mit dem Satz: "Ein Produkt besteht aus vielen Bauteilen".
    Also die eine Entität - "Produkt" ist singular flexiert, die andere - "Bauteil" plural.
    Was ist dir lieber?
    Wählst du singular, so generiert der Dataset-Designer dir für ein Produkt die Datenklasse ProduktRow - was absolut Sinn ergibt: Eine ProduktRow repräsentiert ein Produkt.
    Im Dataset wird allerdings auch die Property Produkt As ProduktDataTable angelegt, was gewöhnungsbedürftig ist: weil eine Tabelle ist natürlich eine Vielheit.
    Richtig richtig wäre also: Produkte As ProduktDataTable - aber dazu isser leider (gottlob) zu dumm.

    Wählst du hingegen die Plural-Flexierung als deinen Favoriten, so generiert der Dataset-Designer dir für ein Produkt die Datenklasse ProdukteRow - was sprachlich falsch ist: Eine ProdukteRow suggeriert vom Wort her, mehrere Produkte zu sein, repräsentiert tatsächlich aber nur ein Produkt.
    Dafür stimmt dann aber die generierte Dataset-Property Produkte As ProdukteDataTable. (naja - ganz richtig ist das auch nicht, es müsste heissen: ProduktDataTable(s.o))

    Also wie mans macht, isses falsch.

    Allerdings nach meiner Erfahrung hantiert man im Code wohl 10-fach häufiger mit einzelnen Datensätzen, als wie man mit den Dataset-Properties für typisierte DataTables hantiert.
    Daher scheint es mir 10-fach wichtiger, dass die einzelne Datenklasse richtig flexiert, als die zugehörige Dataset-Table-Property.

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

    Jo - hier gehts aber um Dataset - da werden die Datenklassen generiert.
    Bei POCO ( = selbstgebastelte Datenklassen) muss man alles selber machen - da kann man es dann auch (s.o.) richtig richtig machen: Public Produkte As List(Of ProduktRow) - sodass die Container-Property plural ist, und die Datenklasse für den einzelnen Datensatz singular.
    Nur musst du dann alles andere auch selber machen: Databinding-Unterstütung, Änderungs-verfolgung, laden, speichern, sortieren, und und und...
    Im Endeffekt das typisierte Dataset von Hand nachprogrammieren - in anderen Worten: Das Rad neu erfinden.

    Die Erfahrung mit neu erfundenen Rädern zeigt aber leider, dass sie zu 99,9% doch nicht so rund werden, wie die Räder, die schon vorher da waren... :(
    Eigentlich ging es mir nur um das Prinzip im Aufbau dieser Datenmodelle, du hast es in ein anderes Thema überführt. Nämlich Sinn und Zweck von POCO Klassen in Winformprojekten.
    Da würde ich solche Datenmodelle auch nicht verwenden, wenn diese Daten an Winform-Elemente gebunden werden müssten.
    Daher gilt das von dir als Ergänzung geschriebene meiner Ansicht nach nur für Winform. Gibt aber auch Winform-Projekte die ein Binden von solchen Klassen ermöglich. Allerdings sehe ich da den Vorteil nicht, dann kann man besser WPF verwenden.

    Zudem ich verwende auch unter Winform POCO-Klassen, die sind nicht gebunden weil es sich hier um zu verarbeitende Daten handelt. Also zigtausende von Datensätzen die manipuliert werden müssen um in einem DB-System untergebracht werden zu können. Hier geht es rein um die Geschwindigkeit und da ist POCO einem designten Dataset haushoch überlegen.

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

    Ich hab bei mir Dutzende aktive Projekte, die alle mit POCOs (oder doch POVOs? egal) als Datenmodellgrundlage laufen und mit WinForms+POCO-DataBinding super laufen. Ist zwar kein neu erfundenes Rad, aber Flossen. Und damit komm ich auch weiter. Nur nehm ich eben einen anderen Transportweg.

    Bezüglich: Produkte As List(Of ProduktRow): da würd ich gleich erstmal den Teil Row entfernen. Die POCO-Klasse hieße einfach nur Produkt oder Product, da ich keine deutschen Begriffe mehr im Code habe. Oder noch nicht einmal mehr Product, weil zu unspezifisch. Aber der hiesige Abschnitt ist Haarspalterei.

    ErfinderDesRades schrieb:

    Allerdings nach meiner Erfahrung hantiert man im Code wohl 10-fach häufiger mit einzelnen Datensätzen, als wie man mit den Dataset-Properties für typisierte DataTables hantiert.
    Das kann ja sein (da ich keine tDS-Projekte mehr im Sortiment habe, kann ich es nicht prüfen und müsste Deine Beispielsolutions aus dem Forum als Beispiel hernehmen), aber geht es ja nicht darum, wie oft ein Datentyp zum Einsatz kommt. Ich dachte es geht darum, wie oft das jeweils falsche Wort zum Einsatz kommt. Und da stellt sich die Frage, in welchen realen Szenarien das der Fall ist.
    1. nicht bei der Abfrage eines Datensatzes mit LINQ, da uns Option Infer die Datentypangabe erspart: Dim FittingCustomer = DataSet.Customers.Single(Function(x) x.PassportID = 1234567890)
    2. Hinzufügen eines Datensatzes per Code: DataSet.Customers.AddCustomersRow(…) - wie häufig wird das bei Verwendung DataBinding gemacht?
    3. der berühmte Doppelcast: dafür gibt es Deine Extension, EdR - aber auch da muss ein Typ angegeben werden. Naja, dafür kann man auch (mei)ne typisierte BindingSource verwenden und das Problem ist auf eine Codestelle im ganzen Projekt reduziert
    4. For Each Customer in DataSet.Customers bzw. DataSet.Customers.ForEach - kein Kommentar, wo der Vorteil beim Plural liegt.
    5. (bitte weitere häufige Stellen nennen, in denen Typangaben zum Einsatz kommen)
    Das Ganze kann gerne weiterdiskutiert werden, das Hauptthema sollte aber nicht verloren gehen.
    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.
    naja, nur weil Type-Inference das Hinschreiben der unglücklich benannten Deklaration erübrigt, ist die Deklaration ja dennoch unglücklich benannt.
    Dein Customer aus 4. ist ja dennoch ein CustomersRow
    Zu 2: Jo - Hinzufügen ist sehr häufig - häufiger als das Durchschleifen einer ganzen Tabelle.
    Überhaupt leiert man sogutwie nie auf den Tabellen rum.
    Man zieht zB das aktuelle Customer(s) aus der Customer(s)BindingSource, und ruft alle der(ss)en Bestellung(en)en ab:
    Dim BestellungenRows = rwCusts.GetBestellungenRows().
    Und ein Bestellungen ist natürlich in Wirklichkeit nur eine Bestellung.
    Oder man zieht das aktuelle Bestellungen aus der BestellungenBindingSource, und ruft de(ss)ren Customers ab:
    dim rwCusts = rwBest.CustomersRow - was sich liest als hätte ein Bestellungen mehrere Customers.

    Tatsächlich ists aber kein Bestellungen, sondern nur eine Bestellung. Und die ist nicht verknüpft mit irgendwelchen Customers, sondern mit genau einem Customer.

    ErfinderDesRades schrieb:

    nur weil Type-Inference das Hinschreiben der unglücklich benannten Deklaration erübrigt, ist die Deklaration ja dennoch unglücklich benannt.
    Ja und? Nur weil ich mit einer Datentypbezeichnung hadere, stört sie mich doch nicht, wenn ich sie im Code implizit verwenden kann, aber nicht lesen muss. Würde mir die Bezeichnung String nicht passen, kann es mir doch egal sein, wenn ich Strings verwenden kann, aber das Wort nicht hinschreiben muss. Offensichtlich haben wir hier falsche Grundvoraussetzungen - was dazu führt, dass wir in unterschiedliche Richtungen denken und diskutieren.

    ErfinderDesRades schrieb:

    Dein Customer aus 4. ist ja dennoch ein CustomersRow
    Und Du würdest Deinem restlichen Post zufolge wohl eher rwCust draus machen. Wo sind wir dann angekommen? Ungarische Notation. Danke, ich verzichte. Ich muss nicht über den Variablennamen daran erinnert werden, womit ich es zu tun habe. Ich nenne das Ding Customer, weil ich einen Kunden modellieren will, keine Kunden-Tabellenzeile.

    ErfinderDesRades schrieb:

    Überhaupt leiert man sogutwie nie auf den Tabellen rum.
    Post#1 setzt hier andere Grundlagen. Datenexport fiele mir noch ein. Ansonsten finde ich das Hinzufügen über Code nur in Kombination mit gleichzeitiger Datenvalidierung relevant. Ich weiß ja nicht, an wievielen Punkten das bei Dir passiert, aber bei mir hält sich das berufsbedingt in Grenzen. Da ackere ich wohl tendenziell mehr Tabellen/Datencontainer in meinen Codes durch.
    Das Pseudobeispiel mit den Bestellungen: Dim OrdersOfSelectedCustomer = Orders.Where(Function(x) x.Customer Is SelectedCustomer) - Anderer Code, anderes Argument, gleiches Resultat. LINQ statt tDS-Code.

    ErfinderDesRades schrieb:

    Tatsächlich ists aber kein Bestellungen, sondern nur eine Bestellung.
    Weiß nicht, was Du damit sagen willst. Es können 0, 1, X Bestellungen sein. Eine Bestellungsansammlung eben.

    Aber ich werde das mit diesem Post beenden, weil es nichts mehr mit dem Ursprungsthema zu tun hat.
    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.

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

    Ja das mit dem Primärschlüssel dachte ich ist offensichtlich weil da so ein Schlüsselsymbol an den Spalten markiert wird.^^

    Eine Gruppe hat ein Lieferdatum
    Also eine Gruppe enthält Pakete oder Produkte.
    Ein Paket enthält Produkte
    Ein Produkt enthält Bauteile
    Ein Produkt hat eine Stückzahl, die aussagt wieviele Kopien davon erzeugt werden.

    Ich muss z.B. ausrechnen können wieviele Produkte in einer Gruppe mit Lieferdatum 12.12.2022 stecken.
    Also im Prinzip haben aus diesem Aspekt die Produkte ein Lieferdatum. In der Realität hat ein Produkt das nicht, sondern höchstens ein Produktionsdatum.

    Naja und das mache ich im Moment ohne Verbindung zwischen den Tabellen und stattdessen hiermit:

    VB.NET-Quellcode

    1. For Each Produkt In DS1.DataTable1
    2. Produkt.Datum = DS1.DataTable3.FindByGroupID(Produkt.GroupID).Datum
    3. Next
    4. Dim q = From t In DS1.DataTable1 Where t.Datum = #12/12/2022#
    5. Dim erg = New Ergebnis With {.Datum = datum, .Stueck = q.Sum(Function(x) x.Stueck)})

    Haudruferzappeltnoch schrieb:

    das mit dem Primärschlüssel dachte ich ist offensichtlich weil da so ein Schlüsselsymbol an den Spalten markiert wird
    Das taucht bei allen Spalten auf, bei denen Unique eingestellt ist. Daher hast Du bei Bauteile 3 Schlüssel. Aber es kann nur einen Primärschlüssel pro Tabelle geben.

    Was bedeutet, dass eine Gruppe Pakete oder Produkte enthält? Enthält eine Gruppe ENTWEDER Pakete ODER Produkte oder ggf. auch beides? Wenn entweder oder, dann gibt es 2 Gruppensorten: Paketgruppen und Produktgruppen, richtig?

    Dein Code stimmt aber nicht, wenn die Gruppe Pakete enthält. Ist das so gewollt?

    Haudruferzappeltnoch schrieb:

    In der Realität hat ein Produkt [kein Lieferdatum]
    Wozu modellierst Du es dann so, wenn es an der Realität vorbeigeht?

    Wie gesagt, die Verbindung (Fachjargon Beziehung oder Relation) der Tabellen führt dazu, dass für eine übergeordnete Tabellenzeile automatisch Code bereitstellt wird, der alle verknüpften Zeilen einer untergeordneten Tabelle zusammensammelt. Eine untergeordnete Tabellenzeile kommt über die Relation an ihre Zeile aus der übergeordneten Tabelle. Und kaskadierendes Löschen ist so möglich. Deine Datensammlung ginge daher auch ohne Relationen. Aber im tDS-Designer sollte dem Betrachter trotzdem mithilfe der Relationen klarwerden, was wie zusammenhängt, auch wenn Du den so zusätzlich generierten Code nicht aktiv in Deinem Projekt nutzt.
    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.

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

    Ne, man kann mehrere Spalten anwählen und als Primärschlüssel festlegen, die FindBy Methode ändert sich da auch bei. FindByColumn1 nimmt einen Parameter entgegen FindByColumn1Column2 nimmt zwei Parameter entgegen. So gehts bei Datenbanken auch, da gibts auch kombinierte Spalten als Primärschlüssel

    Eine Gruppe kann beides enthalten, oder anders gesagt nicht jedes Produkt ist auch in einem Paket. Falls es in einem Paket ist, dann ist dieses Produkt aber nicht selbstständig in der Gruppe, sondern dessen Paket.

    Also auch wenn das Produkt kein Lieferdatum als Datensatz hat, will ich nach Lieferdatum feststellen wieviele Produkte denn in den Gruppen stecken.
    Und mit meinem Ansatz gehts halt so ganz gut, da einfach das Lieferdatum dranzuschreiben.
    An den Tabellen wird nichts geändert, die sind nur ein Abbild damit mein Programm das auswerten kann.

    Wenn es nur um Löschen und Datenkonsistenz geht bei den Relationen, ok, dann hab ichs verstanden, aber dann hilfts mir nicht weiter. Die Konsistenz ist schon vor meinem Programm gewährleistet.
    Ich dachte damit kann man auch Daten kombiniert auswerten.
    Das mit mehreren Primärschlüsseln hatte ich gar nicht probiert. Kommt davon, wenn man nix mehr damit macht.
    Ok, ein Produkt ist entweder lose in der Gruppe oder eingepackt im Paket, welches dann selber in der Gruppe ist.
    Klingt, als ob Du erstmal keine Fragen mehr hättest.
    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.

    VaporiZed schrieb:

    Ok, ein Produkt ist entweder lose in der Gruppe oder eingepackt im Paket, welches dann selber in der Gruppe ist.
    Klingt, als ob Du erstmal keine Fragen mehr hättest.
    Jedenfalls vom Datenmodell her schwierig.
    Eine Vereinfacchung wäre, wenn jedes Produkt immer in einem Paket wäre - dann isses halt ein Paket mit nur eim Produkt.
    Eine Entität (zB Paket, Produkt) ist immer auch eine klasse.
    Und es wird lausig zu coden, wenn man nie weiss, welche klasse nun grad vorliegt: Paket oder Produkt?
    Das führt zu hässlichen Fallunterscheidungen, Casts, Code-Dubletten (die sich dann aber doch bischen unterscheiden).
    Wenn möglich vermeide sowas.