Erweiterter Umgang mit typisiertem DataSet -> Tabellennamen lesen/Namensübergabe etc.

  • VB.NET
  • .NET (FX) 4.0

Es gibt 351 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    Standort 1 kann der Expression-Parser natürlich nicht erkennen, dass das ein SpaltenName ist.
    Der meint Standort sei eine Spalte, und dann kanner mit '1' nix anfangen.

    Escapen von SpaltenNamen
    Das kannste nu escapen, dass ein gültiger Ausdruck bei rauskommt, wie [Standort 1] = test.
    Aber ich würde viel mehr empfehlen, in deinem Datenmodell auf Spaces innerhalb von SpaltenNamen zu verzichten.

    Quoten von Textwerten
    Anschliessend wirds immer noch failen, weil Text-Werte im Expression-Ausdruck müssen ge-singlequoted sein: [Standort 1] = 'test'.
    Zu diese Dinge habich auch Tut gemacht: DataExpressions: Filter und berechnete Spalten im Dataset

    BindingSource.Filter verwenden
    Ich wollte dir eh anraten, diesen Filter nicht mit (untypisierte) DataTable.Select() zu machen, sondern an anderer Stelle BindingSource.Filter zu setzen - wie dann im Tut gezeigt.
    Aber die Syntax solcher Expressions ist dieselbe. (Diese Expressions sind ja eine eigene kleine Abfragesprache. Und deren Doku ist u.a. im Tut verlinkt - auch weil man nicht so leicht drauf kommt, wo die ist.)
    Hab das nun wie folgt gelöst und funktioniert auch :)
    Gibt es noch eine Elegante Methode, eine MsgBox einzubauen wenn keine gefilterten EInträge vorhanden sind?

    VB.NET-Quellcode

    1. Private Sub btnSuche_Click(sender As Object, e As EventArgs) Handles btnSuche.Click
    2. 'TODO Standorterkennung einbauen, es dürfen nur die Mitarbeiter angezeigt werden, die den
    3. 'Standorten hinter dem Mitarbeiter entsprechen
    4. 'Falls als Admin eingeloggt darf alles gezeigt werden
    5. Dim suchSpalte As DataColumn
    6. Dim suchBegriff As String = Me.TbSuche.Text
    7. Dim inaktiv As CheckState = Me.CbInaktiv.CheckState
    8. Dim ds As dtsLogistik = frmEinstellungenDaten.DtsLogistik
    9. Dim bs As BindingSource = frmEinstellungenDaten.MitarbeiterBindingSource
    10. Dim tb As MitarbeiterDataTable = ds.Mitarbeiter
    11. Dim dgv As DataGridView = Me.DataGridView1
    12. If Not suchBegriff = "" Then
    13. Select Case True
    14. Case rbtnName.Checked
    15. suchSpalte = tb.NameVornameColumn
    16. Case rbtnStandort.Checked
    17. suchSpalte = tb.Standort_1Column
    18. Case rbtnFunktion.Checked
    19. suchSpalte = tb.FunktionColumn
    20. Case Else
    21. suchSpalte = tb.NameVornameColumn
    22. End Select
    23. Dim expression As String = Nothing
    24. If inaktiv = CheckState.Checked Then
    25. expression = $"[{suchSpalte}] Like '*{suchBegriff}*'"
    26. Else
    27. expression = $"[{suchSpalte}] Like '*{suchBegriff}*' AND Aktiv = True"
    28. End If
    29. dgv.DataSource = bs
    30. bs.Filter = expression
    31. Else
    32. dgv.DataSource = bs
    33. End If
    34. dgv.Columns(tb.IDColumn.ToString).Visible = False
    35. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    naja, bindingsource.Count sagt dir ja, ob sie leer ist.

    Was anneres:
    Bindingsources erstellt man doch nicht im Code - sowas designed man im Designer!
    Und dem DGV wird auch nicht per Code die DataSource gesetzt - ebenfalls Designer-Work das.
    Bleibt von deine Methode übrig:
    ...
    Achnee geht ja garnet.
    Du machst da ja iwie eine ganz hanebüchene Lösung des formübergreifenden Databindings.
    Indem du in ein anderes Form reingrabschst - wobei auch nicht zwischen Instanz und Datentyp unterschieden wird.
    Ja gut - wenn du so arbeiten willst, kannst du das aktuelle Form (ich weiss nicht wie's heisst), halt nicht im Designer designen - oder vielleicht doch, zumindest eine Weile, und dann andere Probleme, wasweissich.

    Ich täte dir jdfs. meine Helperlein fürs formübergreifende Databinding empfehlen.
    In einen Datentyp grabschen, der gleichzeitig eine Instanz ist, was aber nur in VB geht, aber nur mit Forms - dieses 'Feature' zu nutzen täte ich sehr von abraten.
    Indem es den Unterschied zwischen Instanz und Datentyp ausmerzt, trotzdem aber funktioniert, verhindert es u.a., dass du objektorientiert denken lernen kannst.
    Auch verhindert es, dass du den Form-Designer so nutzst, wie er vorgesehen ist.
    Und wenn mittelfristig anspruchsvollere Aufgaben zu lösen sind, erzeugt dieser Ansatz nochma ganz andere Probleme.



    ach - und nochmal Erinnerung:

    Ich schrieb:

    Aber ich würde viel mehr empfehlen, in deinem Datenmodell auf Spaces innerhalb von SpaltenNamen zu verzichten.
    Kurzfristig ist das Problem nu gelöst, aber dennoch hast du sonen problematischen SpaltenNamen in deim Datenmodell.
    Wie lautet etwa die typisierte Property der MitarbeiterRow, die daraus generiert wird?
    Also VisualBasic kann mit so Escapaden umgehen, auch mit Umlauten in Spalten- und Tabellen-Namen und wasweissich.
    Nur kannst du immer damit umgehen, wie Visualbasic damit umgeht?

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

    Also, was die Benennung der Spalten angeht: das werde ich noch korrigieren und mir deinen "Rad"schlag zu Herzen nehmen.
    Das mit den [] war für diesen Bereich ein Test, ob's denn überhaupt geht.

    Zu dem anderen Thema:
    Ich hab eine Form mit Labels und leeren Textboxen (form1.png), mit einem Klick auf den Button öffnet sich die
    Form für die Mitarbeitersuche mit dem DGV, um das es hier die ganze Zeit geht. (form2.png)

    Über die Filter lass' ich mir den / die entsprechenden Mitarbeiter anzeigen, nach Doppelklick auf den angezeigten Datensatz im DGV
    sollen die Werte in die Form mit den leeren Textboxen übernommen werden. Wie soll ich das denn über den Designer abbilden?

    Ich wüsste auch nicht, was daran unüblich wäre - unser WaWi-System arbeitet nur so...

    Für das Übertragen der Inhalte an die Textboxen hab' ich mir schon was gebaut, er zeigt mir aber keine Inhalte an:

    form1:

    VB.NET-Quellcode

    1. Public Property MitarbeiterDetail() As DataRow
    2. Get
    3. Return _mitarbeiterRow
    4. End Get
    5. Set(value As DataRow)
    6. _mitarbeiterRow = value
    7. Me.TextBox1.Text = _mitarbeiterRow(1).ToString
    8. Me.TextBox2.Text = _mitarbeiterRow(2).ToString
    9. End Set
    10. End Property


    form2:

    VB.NET-Quellcode

    1. Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDoubleClick
    2. Msg_information("test")
    3. Dim editFrm As New frmStammdatenMitarbeiter
    4. Dim dgv As DataGridView = DataGridView1
    5. Dim bs As BindingSource = frmEinstellungenDaten.MitarbeiterBindingSource
    6. editFrm.MitarbeiterDetail = CType(bs.Current, DataRowView).Row
    7. editFrm.BringToFront()
    8. Me.Close()
    9. End Sub


    Edit:
    Ich habe den Code nun erweitert, sodass mir beim Befüllen der Textboxen auch die DataBindings erstellt werden.
    Hab' die Werte dazu mal in meinen Debugger abgefangen - da sieht alles korrekt aus, allerdings steht kein Text in den Boxen drin :(

    VB.NET-Quellcode

    1. Dim _mitarbeiterRow As DataRow
    2. Dim bs As BindingSource = frmEinstellungenDaten.MitarbeiterBindingSource
    3. Dim ds As dtsLogistik = frmEinstellungenDaten.DtsLogistik
    4. Dim tb As DataTable = ds.Mitarbeiter
    5. Public Property MitarbeiterDetail() As DataRow
    6. Get
    7. Return _mitarbeiterRow
    8. End Get
    9. Set(value As DataRow)
    10. _mitarbeiterRow = value
    11. For i As Integer = 1 To 15
    12. With Me.Controls.Item("TextBox" & i)
    13. .DataBindings.Add(New Binding("Text", bs, tb.Columns(i).ToString, True, DataSourceUpdateMode.OnPropertyChanged))
    14. Debug_msg("Spalten auslesen", tb.Columns(i).ToString)
    15. .Text = _mitarbeiterRow(i).ToString
    16. Debug_msg("Werte auslesen", _mitarbeiterRow(i).ToString)
    17. End With
    18. Next
    19. End Set
    20. End Property


    Debugger = unbenannt.png
    Bilder
    • form1.png

      57,98 kB, 972×811, 91 mal angesehen
    • form2.png

      84,47 kB, 2.004×583, 83 mal angesehen
    • unbenannt.png

      449,55 kB, 1.813×945, 87 mal angesehen
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

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

    tragl schrieb:

    Ich wüsste auch nicht, was daran unüblich wäre - unser WaWi-System arbeitet nur so...
    Den Geschäftsvorgang so vorzusehen ist total üblich und sinnvoll.
    Aber die Implementierung ist unüblich.
    Also hanebüchen ist dieser Grabsch in einen Datentypen, der gleichzeitig eine Instanz ist:

    VB.NET-Quellcode

    1. Dim ds As dtsLogistik = frmEinstellungenDaten.DtsLogistik
    2. Dim bs As BindingSource = frmEinstellungenDaten.MitarbeiterBindingSource
    Das ist Anti-OOP, denn frmEinstellungenDaten ist ein Datentyp, und nirgends in deim Code erstellst du eine Instanz davon.
    Kannste auch nicht, bzw. dann würde, was du da hast nicht funktionieren.
    Wie gesagt: Diese Vorgehensweise verunmöglicht es, objektorientiert denken zu lernen.

    Ich komm dir noch einmal mit meim formübergreifendem Databinding.
    Dann brauchst du kein KrimsKrams zu schreiben, um Textboxen zu befüllen.
    Auch Textboxen bindet man ans typDataset, und das macht man im Designer.
    im 4-Views-Video ists in "DetailView" gezeigt.

    Nur funzt das net bei mehreren Forms, weil formübergreifendem Databinding eben von Haus aus nicht unterstützt wird.
    Daher meine Helperleins.

    Kannst das Projekt nochma anhängen, dann kann ich das einbasteln - wirst staunen.
    Hey, danke für das Angebot. Den aktuellen Stand hab' ich dir als Zip angehangen.
    Ich freu' mich sehr darüber, dass ich das sozuagen mit dir "durchkauen" kann und die Sache mit dem formübergreifenden DataSet ist mir aktuell
    echt noch sehr schleierhaft.

    Wenn's dann zuviel wird, dann musst du bitte Bescheid geben - dann muss ich mir leider ggs. woanders Rat (oder Rad) suchen :) aber ich hab
    schon einiges von dir lernen können. Danke nochmal an der Stelle dafür - ist nicht selbstverständlich.

    Zum Thema Datentyp / Objekt
    Hätte ich also so vorgehen müssen:

    VB.NET-Quellcode

    1. Dim frmDTS As Form = frmEinstellungen
    2. Dim ds As dtsLogistik = frmDTS.DtsLogistik


    usw.? Find ich sehr umständlich, aber wenn's zum OOP dazu gehört werd ich das natürlich künftig so umsetzen.
    Bin wie gesagt von VBA noch sehr verwöhnt.
    Dateien
    • LogistikTool.zip

      (348,64 kB, 73 mal heruntergeladen, zuletzt: )
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    nein, das ist schon Teil 3
    Dort In der "Introduction" ist doch auf die beiden vorherigen Teile verlinkt.
    Ich meinte in post #27 übrigens das Datenmodell-Design, nicht iwelches Gui-Design.



    Zu deim LogistikTool: frmMitarbeiterStammDaten find ich vom User-Workflow her doch bisserl abwegig. Das konnte man ja öffnen, ohne dass ein Mitarbeiter angezeigt wurde.
    Was sollte da passieren, wenn man da dann was eingab, ohne dass zuvor einer gesucht wurde?
    habich geändert, dass da nu meist erst eine MA-Suche auszuführen ist.

    Es handelt sich bei frmMitarbeiterStammDaten ja um einen DetailView - also lauter EinzelControls zeigen Eigenschaften eines Datensatzes.
    Sowas mache ich nur als Dialog, wenn man einen Datensatz bearbeiten/neu anlegen will: öffnen, bearbeiten schliessen.
    In einer "stehenden Ansicht" kombiniere ich einen DetailView immer immer mit einem DGV, wo man also den Mitarbeiter im DGV aussuchen kann, der im DetailView angezeigt ist.
    Da kann man auch einen Suche-Filter dranmachen, oder auch einen Filter-Dialog aufrufen, wenns zuviele Mitarbeiter werden, die sich da im DGV tummeln.
    Aber sone Firma muss man erstmal haben.

    Nachwievor wird da in Datentypen reingegrabscht, aber das liegt auch an deine MDI-Struktur.
    Ich mag MDI ja nicht, ich finde ein TabControl besser.
    Da kann man nicht die ChildForms zumachen, und dann sind sie weg.
    Dateien

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

    Jetzt knallt er beim Starten einen Fehler für den Tree rein (siehe Bild) - das hat doch bisher gefunzt?
    Ich vermute weil "mode" - also My.Settings.Mitarbeiter_funktion nicht mehr gefüllt wird, das das modul dazu rausgeflogen ist.
    EDIT: lag daran, hab ich beheben können.

    Ansonsten kenn' ich das so (zumindest aus unserem WaWi), dass die DetailForm leer ist beim Starten und man erstmal jemanden (Mitarbeiter, Kunden etc.) suchen muss.
    Den kann man dann in der DetailForm bearbeiten. Das wollte ich eigentlich auch so beibehalten, sodass das Programm unserem WaWi so nah wie möglich von der Bedienung her kommt
    weil - du wirst es vermuten - nicht alle so fit in der IT sind wie ich oder evtl. noch 1-2 andere Leute. Für die ist eine großere Umstellung erstmal Bullshit :)

    Daher auch das mit den Parent-Child-Forms - was mir persönlich im Übrigen auch ganz gut gefällt. Ich find dagegen das TabControl nicht ansprechend.
    Was genau sollte denn an meinem Design des DataSets noch optimiert werden? Hatte mir damit die vorige Nacht um die Ohren gehauen, um die Beziehungen zu setzen.

    Teil2 schau' ich mir die Tage dann an, der Code ansich (der von dir bearbeitete) sieht für mich schlüssig aus, auch wenn ich mich mit den "Helpers" noch befassen muss.
    (Wann werden die wie und wo eingesetzt und was für Funktionen stecken dahinter).

    Zuletzt:
    Die Module, die ich drin hatte sind ja jetzt weg (hattest du schon gesagt dass du das nicht richtig findest). Wo pack' ich z.B.
    meine Abhandlungen für mein Debug-Windows hin? In die Form "frmDebug" selbst als Public Sub?

    Die "Public Sub New()" mit erster Zeile "InitalizeComponent()" ersetzt das Form-Load-Event?,richtig?
    Kann/soll ich da alles "reinknallen", was beim Start der Anwendung abgehandelt werden muss?

    ...muss morgen arbeiten, danach wühl' ich mich mal komplett durch das Projekt um hoffentlich das Verständnis für alles aufzubringen :)
    ist halt sehr viel Neuland dabei für mich.
    Bilder
    • unbenannt.png

      449,55 kB, 1.830×259, 83 mal angesehen
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Jo, auch'n datengetriebener Fehler. Settings-Werte kommen beim Zippen und Anhängen nicht immer mit.
    Also folgende Zeile (#4) zufügen:

    VB.NET-Quellcode

    1. Public Sub FillTree(tv As TreeView)
    2. tv.Nodes.Clear()
    3. Dim mode As String = My.Settings.Mitarbeiter_Funktion
    4. If mode = "" Then mode = "TL"
    5. Dim filteredSorted = Tree.Select($"{mode} = True").Cast(Of TreeRow).OrderBy(Function(rw) rw.SortKey).ToList
    6. Dim nodeCollections = {tv.Nodes, Nothing, Nothing, Nothing}
    7. For Each rw In filteredSorted
    8. Dim iNodes = rw.Nr.Split("."c).Length - 1
    9. nodeCollections(iNodes + 1) = nodeCollections(iNodes).Add($"{rw.Key}", $"{rw.Nr} = {rw.Bezeichnung}").Nodes
    10. Next
    11. tv.ExpandAll()
    12. End Sub

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

    Bin gerade dabei, das Datenbankdesign nochmal ordentlich "aufzumalen" bzw. aufzuzeigen. Gibt es eine Möglichkeit eine Expression zu setzen,
    die z.B. aus einer Tabelle mit "Name" und "Vorname" automatisch in dem feld (expNameVorname) die beiden zusammenfügt (z.B. "Name, Vorname")?

    Die Expression dazu habe ich gefunden

    Quellcode

    1. Column1 + ', ' + Column2
    er meckert nur weil "expNameVorname" in Beziehungen verwendet wird -
    da schau' ich mal, wie ich das hin bekomme.

    Das neue Design möchte ich dir dann gerne hier mal zeigen, sodass du drüber schauen kannst ob das Sinn macht?

    Edit: Hier mal das Design aufgezeigt. Ist es in Ordnung statt Leerzeichen Punkte zu verwenden in den Spaltenbezeichnungen oder lieber eine # dazwischen machen?
    dbdesigner.page.link/rs5qYhvnDKz9QKRV8

    LG
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

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

    Warum nimmst du diesen Datenmodell-Maler?
    Du kannst doch einfach ein typisiertes Dataset gestalten im Dataset-Designer. Der bietet doch dieselbe Ansicht.
    Sone .xsd kannste auch anhängen, dann kann ich die im visualStudio öffnen und verwüsten.
    Bei den Pfeilen im Maler kann ich nicht sehen, welche Spalte wie mit welcher anneren verknüpft ist.
    Auch kann ich die AllowNull-einstellungen nicht sehen.
    Und vieles andere auch nicht.

    Edit: Achso - kann man auch so leidlich nachgucken. Nur die Relationen habich noch nicht gefunden



    Ich mach keine Spaces in Datenmodell-Objekte, und auch keine .. Aus den Objekten wird Code generiert, und wenn meine Spalte "Teamleiter.Standort" heisst, dann weiss ich nicht, was für einen CodeNamen VisualStudio daraus generiert.
    Allenfalls verwende ich _ - weil das ist auch als CodeName gültig.



    Ansonsten empfehle ich nochmal Teil2 des englischen Tuts.
    ZB Entitäten sollten singular sein.
    Und von Umlauten taetich auch sehr abraten.
    Und Nulls würde ich viel weniger erlauben - eiglich nur, gelegentlich bei End-Datumsen von Vorgängen, die noch nciht beendet sind.
    String-Felder brauchen nicht Nullable sein - macht nur Probleme.
    Lies Teil2

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

    ok, ich übertrag' das mal in den DataSet Designer und schick' dir die .xsd
    Die Aenderungen (Umlaute,Trennsymbole) mach ich gleich mit. Ich müsste dann eben wissen, ob die Relationen so passen.
    Ich verbinde alle Felder, die miteinander zu tun haben und unterscheide dabei nach "Haupttabelle" und "Subtabelle" also ein Eintrag in der Haupttabelle
    darf dann in der Subtabelle stehen.

    Teil2 werd' ich definitv lesen (vermutlich auch Teil1 und 3 - mehr Wissen schadet ja nicht, ich tu' mich nur mit dem Englisch-Lesen
    schwer)

    Ich meld' mich wieder wenn ich das übertragen hab :)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Hmm - das muss doch zu schaffen sein:
    1. No entity without PrimaryKey
    2. Short, meaningful Naming
      The designer generates lots of classes, Properties, Events, Methods - all of their Names are derived from the Name-Base, you set in the Datamodel. So a small suboptimalism will multiplicates a hundred times, and you have to deal with it as long as the program exists
    3. Name PrimaryKeys simply ID - always - (shorter and meaningfuller is impossible ;) )
    4. Name ForeignKeys by ParentTableName + "ID"
      Eg Order.CustomerID, or Article.CategoryID. If done so, everybody immediately recognizes Primkeys, ForeignKeys, and to what Parent-Table the latter refer.
    5. Don't frighten name-conflicts
      in a typed Model the same name, used in different tables do not cause name-conflicts, not even indirectly.
      It's impossible to mix up an Category.Name with an Article.Name, because Category and Article are completly different and independend classes.
    6. In cases feel free to use your own language.
      Shortness and Meaningfullness to you and your collegues may be more important than satisfying more abstract demands of an international standard. A Model can contain about hundreds of terms, some of them difficult to explain - it's very hard, to find always the exact matching english expression.
    7. Make the model strict - avoid AllowNull
      By default the designer configures properties which are allowed to be un-set. Don't do so! Try always to enforce, that properties are to set, and only allow Null, if you have good reasons for that.
      Instead of AllowNull mostly one can configure a DefaultValue, eg String="", Bool=False, Int=0, and stuff like that. That prevents NotNullAllowed-Exceptions as well, since a NullValue can't occur - in doubt always the DefaultValue is present.
      Trust me: That trick eases the later coding against the Datamodel significantly
    8. Make the model strict - try use ForeignkeyConstraint and cascaded Deletion
      Usually the childrows become invalid, when a parentrow is deleted. For that, simply configure cascaded deletion, and you don't need to think about that further.
      UpdateRule.Cascade
      This one becomes important, when accessing to real Databases. But better get used to do so from the beginning - it doesn't hurt.
    9. Respect Datatypes
      I'm heartbroken, that I must include this point, but I've seen so often Numbers, stored as Strings, Dates, stored as Strings, Booleans, stored as Strings, such hurts :(
    10. No Prefixes
      Prefixes, if they make sense at all, their purpose is to distinguish several types. In a relational Datamodel there are only Tables. So what's the use, to prefix each Table with "tbl"? Everybody knows by himself, that OrderDataset.Article is a Table - what else such should be?
    11. Name singular
      As said, "Entity" means both: the concept of a record, and the particular concrete record. Yes, a Table also defines the concept of the contained records, and a Table must be seen as plural.
      But in Code you will deal mostly with the particular DataRow. And when the Table is named plural, then the Dataset-Designer generates the particular DataRow also as plural - and that is definitely wrong.
      Eg the Method OrderDts.Articles.AddArticlesRow(...) expresses by its naming, that it adds several Articles - which is not correct - the Method adds only exact one Article.
      For that name Article singular, and the Dataset-Designer will generate: OrderDts.Article.AddArticleRow(...), which does what it says.
    Paar Dinge fallen mir auf:
    Singular benamen (wie gesagt)
    Standort, User und paar annere haben keine ID, sondern verwenden ihren Namen als PK.
    Das gibt Probleme, wenn der Name mal geändert werden soll.
    Dann natürlich die ganzen Zeichen(üä- ./), die nur mit iwelchen Extrawürsten in CodeNamen übertragen werden können.
    Dann hast du viel zuviel AllowNull drinne - wie auf englisch gesagt: Nicht erlauben - statt dessen einen Defaultwert einsetzen, etwa "" für String, 0 für Integer, (oder auch -1 , je nachdem).
    Und die Relationen wie auf englisch gesagt: mit ForeignKey und Löschweitergabe.
    Einige Namen gehen noch kürzer - statt 'nummer' nehm ich immer nur 'Nr'.
    Aber du hast keine Prefixe, und auch keine unverständlichen Abkürzungen - dassis schoma sehr gut.

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

    Hi, ich hab' dir die xsd mal angehangen - dazu hab ich für mich eine Excel-Tabelle erstellt mit Zusatzinfo's weil man nicht alles auf den ersten Blick erkennt im Designer.
    Mit den Soll-Einstellungen (z.B. soll der Integer nur 5 Stellen haben) hab ich meine Probleme
    und leider gibt's ein Problem, dass er eine Expression-Zelle wohl nicht in Beziehung setzen kann. Das wäre in dem Fall die "expNameVorname" in [Mitarbeiter], wo automatisch der Name und Vorname addiert werden soll (Name + ', ' + Vorname)

    Ansonsten hab ich erstmal nur "Beziehungen" gesetzt, ich muss mir noch raussuchen, was genau die Begrifflichkeiten bedeuten:

    - Sowohl Beziehungs- als auch Fremdschlüsseleinschränkung
    - Nur Fremdschlüsseleinschränkung
    - Nur Beziehung
    - Geschachtelte Beziehung

    Bzgl. der Regeln:

    - Aktualisierungsregel: ist klar, soll er auch in dem Child ändern, wenn der Parent geändert wird
    - Löschregel: Hier sollen eben keine Datensätze gelöscht werden nur weil ich z.B. einen Mitarbeiter lösche. Dazu darf der Mitarbeiter ruhig bestehen bleiben und der würde dann auf "Aktiv = False" gesetzt.
    Eine Lösung mit der ich leben könnte, wäre dass der Eintrag Mitarbeiter dann auf "" gesetzt wird - oder hättest du da eine bessere Idee dazu?

    Ich hab' die Regeln von deinem letzten (englischen) Beitrag soweit befolgt. Mit englisch lesen hab' ich auch kein Problem, kann das sogar recht gut verstehen allerdings raucht mir im Bezug Programmieren
    aktuell sowieso der Kopf weil's einfach jede Menge Input (jeden Tag!) ist und dann kommt noch englisch lesen obendrauf :)

    -ID's hab ich noch hinzugefügt
    -Sonderzeichen sind weg
    -allownull ist bis auf 2 oder 3 Ausnahmen weg
    -bezeichnungen sind teilweise gekürzt

    Dann warte ich mal auf deinen Kugelhagel an Kritik :)
    Dateien
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    gleichma ohne reingekiekt zu haben zu

    tragl schrieb:

    - Sowohl Beziehungs- als auch Fremdschlüsseleinschränkung
    - Nur Fremdschlüsseleinschränkung
    - Nur Beziehung
    - Geschachtelte Beziehung

    Meine Vorzugsvariante einer Beziehung ist:
    • Sowohl Beziehungs- als auch Fremdschlüsseleinschränkung (alias: "referentielle Integrität")
      erzwingt, dass ein untergeordneter Datensatz einen gültigen FremdSchlüsselWert beinhaltet.
      So kann nicht vorkommen, dass eine Bestellung existiert, die auf einen Kunden verweist, dens nicht gibt.
    • Löschweitergabe (alias: "Löschregel: Cascade", alias: "On Delete Cascade", (weitere Aliasse...))
      Wenn ein Kunde gelöscht wird, dann sollen auch alle seine Bestellungen gelöscht werden
    • Regel akualisieren
      Ist was anneres, als was du denkst. Hier werden alle Fremdschlüssel untergeordneter Datensätze automatisch nachgezogen, wenn im übergeordneten Datensatz der PK geändert wird.
      Da man einen PK niemals ändert, ist das nicht soo relevant. Wird allerdings später, wenn eine DB hinterlegt wird, wichtig. Und tut auch nicht weh, es jetzt schon einzustellen
    • geschachtelte Beziehung: nicht relevant.
      Das bestimmt, wie inne Dataset-Datei beim Abspeichern das Xml generiert wird.
      Kann sein, dasses noch iwas anneres bestimmt, was ich nicht weiss - vielleicht eine Geschwindigkeits-Optimierung - wie gesagt: nicht relevant, und ich schalte das nie an.
    Wenn du deine Mitarbeiter nicht löschen willst, sondern nur Aktiv=False einstellen, ist das i.O. - dann werden sie eben nicht gelöscht.
    Trotzdem sollteste die Relation mit Löschweitergabe einrichten - einfach, damit das Dataset sich vorhersehbar verhält.
    Ausserdem halte ich für gut möglich, dass du im Admin-Modus einen Mitarbeiter durchaus löschen können möchtest.



    Übrigens für deine Standort-Mitarbeiter-Relationen - es sind ja zwei - muss mans wohl gleich anders machen als meine VorzugsVariante:
    • Löschregel: On Delete SetNull
      also dass der untergeordnete Mitarbeiter-Datensatz mit einem Standort nicht gelöscht wird, sondern nur sein Standort1 oder Standort2 - Fremdschlüssel wird auf Null gesetzt.
    Keine Ahnung, welche Fiesematenten sich daraus in der Datenverarbeitung ergeben, aber wirste ja sehen.
    Ich hoffe nur, dass man da trotzdem einen InnerJoin - View mit basteln kann.

    Eigentlich ist das ein unsauberes Datenmodell mit Standort1, Standort2, und läuft ja auch vor die Wand, wenn ein Mitarbeiter mal 3 Standorte bewältigen soll
    Eigentlich müsstest du eine Zwischentabelle einrichten, über die du einen Mitarbeiter mit mehreren Standorten verknüpfen kannst (m:n-Relation)



    tragl schrieb:

    Dann warte ich mal auf deinen Kugelhagel an Kritik
    • Hmm - in gewisser Hinsicht hat sich ja nicht viel getan, oder?
      Standorte, PLZListe, Fahrzeuge, Touren - alles nachwievor plural.
    • PLZListe - ist das ühaupt ein angemessener Name?
      Mir sieht die Tabelle eher wie ein TourStop aus, wenn ich das recht versteh, würde ich das auch so benennen.
    Guck - mit bischen Liebe zum Detail kann man das Dataset auch noch übersichtlich anordnen - die Relationen fast kreuzungsfrei!
    Bilder
    • dtsNeu00.png

      61,76 kB, 801×896, 311 mal angesehen

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

    Hmh..

    -Plural: Sind doch nur die TabellenNamen - die Spaltenbezeichnungen sind alle singular, dachte das wäre das Wichtigste
    -PLZListe: ist eine Liste, die beinhaltet welche Tournummer und welcher Standort für die Belieferung in der PLZ zuständig ist. Man könnte es auch ausschreiben und "Postleitzahlenliste" nennen :)
    -Löschweitergabe: Ist meiner Ansicht nach ein heißes Eisen, wenn dabei ganze Datensätze mit gelöscht werden. Ein Programmierfehler und die Mitarbeiter können Datensätze versehentlich löschen, das wäre nicht gut.

    Bzgl m:n habe ich schon von gehört und auch gelesen, komme aber gerade nicht drauf wie ich das mit den Standorten der Mitarbeiter lösen soll.
    Die weitere Programmlogik muss auch später auf ggf. alle 3 hinterlegten Standorte "hören", sodass der Teamleiter die Daten seiner Mitarbeiter aus den 3 Standorten sieht
    und eben nicht die der Standorte, die nicht hinterlegt sind.. Was schlägst du für eine Lösung vor?

    Die Anordnung habe ich auf der Arbeit angefangen und eben nach der Arbeit noch "auf die Schnelle" fertig gemacht, damit das nicht wieder eine Nachtschicht wird ;) außerdem reagiert der Designer empfindlich auf unterschiedliche Auflösungen.
    Auf der Arbeit hab ich 2 24er Dell-Monitore mit 1600x1440 oder was und hier daheim 3840x2160, bei mir daheim sah das dann direkt wieder anders aus als auf Arbeit - deshalb war mit das erstmal 2.rangig.
    Die Mühen hab ich allerdings in die Datentypen und AllowNull etc. gesteckt. Was ich noch machen muss ist die Feldeinstellungen der einzelnen Spalten machen, dass später z.B. automatisch Dropdowns und Checkboxen generiert werden - das mach' ich dann aber wenn das DataSet steht.

    Ansonsten ist es halt kein typisches Lieferant-Artikel-Kunde Konstrukt sondern vermutlich schon was anspruchsvoller. Da werden auch noch einige Tabellen hinzukommen.
    Hast du schon was rausfinden können mit der Expression-Zelle expNameVorname? Die bekomme ich nämlich leider in keine Relation gesetzt wenn die Expression eingetragen ist.

    Und generell: Wenn ich später Summen etc. abbilden möchte, dann muss ich dafür ein neues Feld in der Tabelle anlegen, richtig? (Wenn's denn gespeichert werden soll vermute ich)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    tja, leider kann ich das Excel-File nur öffnen, aber keine Änderungen speichern - weil ich hab kein Excel.
    Sonst wäre das eine gute Möglichkeit mein Senf dazu zu geben.
    Aber mein Senf ist ja erstmal nur stereotyp:

    AllowNull ist böse.
    Stattdessen - wenns irgend geht - je nach Datentyp (und Anwendungsfall) Defaultwerte festlegen, die ebensogut "nicht gesetzt" bedeuten.
    • für int: 0 oder auch -1, wenn explizit "nicht gesetzt" ausgesagt werden soll.
    • für decimal: 0 oder auch -1, wenn explizit "nicht gesetzt" ausgesagt werden soll.
    • für String: "" - also im PropertyGrid bei der "DefaultValue"-Property den voreingestellten <DbNull> eintrag rauslöschen.
    • bei DateTime kann man einen MinimalWert oder MaximalWert reinschreiben - muss man evtl. später, wenn eine Datenbank hinterlegt wird, an den dortigen Wertebereich anpassen

    Die Überlegungen zum Format kannste dir sparen - son Kleinkram kann (braucht) man im Dataset nicht einstellen.
    Bei PLZ die Formatierung mit aufgefüllten 0en kriegt man hin - zumindest in DGV-Zellen.



    -Plural: Sind doch nur die TabellenNamen - die Spaltenbezeichnungen sind alle singular, dachte das wäre das Wichtigste
    Nö - die TabellenNamen sind wichtiger.
    Ein SpaltenName wird im Code zu einer Property.
    Ein TabellenName wird im Code zu 1) einer Property, 2) einer Klasse (FahrzeugeDataTable), 3) mehreren Methoden, 4) mehrere Events, 5) und noch eine Klasse (FahrzeugeRow).
    Was soll das sein, ein FahrzeugeRow? Es sind keine Fahrzeuge, es ist nur ein Fahrzeug!
    Und mit der (dann irreführend benamten) typisierten Row-Klasse wirste die ganze Zeit sehr viel im Code zu tun haben - das können 10 Jahre werden - also kümmer dich um die perfekte Benamung!

    Und generell: Wenn ich später Summen etc. abbilden möchte, dann muss ich dafür ein neues Feld in der Tabelle anlegen, richtig? (Wenn's denn gespeichert werden soll vermute ich)
    Jo - Sowas handelt man möglichst über berechnete Spalten ab.

    Hast du schon was rausfinden können mit der Expression-Zelle expNameVorname? Die bekomme ich nämlich leider in keine Relation gesetzt wenn die Expression eingetragen ist.
    Nö - geht glaub net. Wofür wäre das nötig?
    Man kann eine Relation mit mehreren Spalten festlegen, etwa mit den Spalten Name, Vorname.
    Aber ich mag solche Extrawürste nicht.
    Ich ziehe meine Relationen am liebsten per PK und feddich.

    -Löschweitergabe: Ist meiner Ansicht nach ein heißes Eisen, wenn dabei ganze Datensätze mit gelöscht werden. Ein Programmierfehler und die Mitarbeiter können Datensätze versehentlich löschen, das wäre nicht gut.
    Kein Problem: Mach halt keinen Lösch-Button hin. Und wenn DGV - deaktiviere die Löschmöglichkeit - das sind 2 Klicks.

    Viel problematischer, wenn die Relation wg. unterlassener Löschweitergabe korrupte Daten zulässt.
    Korrupte Daten machen endlos Ärger, und sind oft kaum zu reparieren.
    Und wie gesagt: als Admin wirst du sehr wohl mal einen MA löschen wollen.

    Bzgl m:n
    Da hilft nix - da muss man relationale Datenmodellierung lernen.
    Grundlagen: Relationale Datenmodellierung
    (Entspricht mit paar Abzüge dem englischen Tut, Teil 1)

    Was ich noch machen muss ist die Feldeinstellungen der einzelnen Spalten machen, dass später z.B. automatisch Dropdowns und Checkboxen generiert werden
    Nee - das macht man nicht im Dataset.
    Man kann sowas für DetailViews in iwelchen DatenTool-Optionen einstellen.
    Das dumme aber, dass bei direkt generierte Comboboxen das Databinding falsch generiert ist - also Comboboxen musste händisch machen.

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

    ErfinderDesRades schrieb:

    AllowNull ist böse.
    Stattdessen - wenns irgend geht - je nach Datentyp (und Anwendungsfall) Defaultwerte festlegen, die ebensogut "nicht gesetzt" bedeuten.

    für int: 0 oder auch -1, wenn explizit "nicht gesetzt" ausgesagt werden soll.
    für decimal: 0 oder auch -1, wenn explizit "nicht gesetzt" ausgesagt werden soll.
    für String: "" - also im PropertyGrid bei der "DefaultValue"-Property den voreingestellten <DbNull> eintrag rauslöschen.
    bei DateTime kann man einen MinimalWert oder MaximalWert reinschreiben - muss man evtl. später, wenn eine Datenbank hinterlegt wird, an den dortigen Wertebereich anpassen


    genau das hab' ich doch bei allen Datenfeldern (außer bei 2 oder 3 Stück, die Null sein dürfen weil's eben noch kein End-Datum gibt - ansonsten hatte ich das überall eingestellt.
    Wie sähe die Relation dann aus? Im Parent die Felder "Name" und "Vorname" wählen und im Child dann nur "Mitarbeiter", werden die dort zusammengefügt? Diese Extrawurst seh' ich als notwendig da beim Anlegen
    der Mitarbeiter die Leute bestimmt mal mit und mal ohne leerzeichen nach dem Komma arbeiten oder das Komma bestimmt auch mal weg lassen. Deshalb hatte ich das in den Mitarbeiter-"Stammdaten" aufgeteilt, in den anderen
    Tables wird es ja nur aus der "parent gezogen" und sollte da zusammengeführt erscheinen.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: