Typisiertes Dataset - Löschen von verknüpften Datensätzen

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

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

    Typisiertes Dataset - Löschen von verknüpften Datensätzen

    Hallo Leute,

    Ich habe ein Dataset mit verknüpften Tabellen, u.a. einer Tabelle Vorrichtungen und einer Tabelle VorrichtungArtikelnummer.
    Die Tabelle VorrichtungArtikelnummer enthält als Fremdschlüssel die VorrichtungID. Die Tabellen sind mit einer Relation versehen,
    die Regeln für Insert, Update, Delete stehen auf Cascade.

    Ich bin davon ausgegangen, dass wenn ich eine Vorrichtung lösche, löscht er auch die zugehörigen Einträge in der VorrichtungArtikelnummer.

    Das klappt aber leider nicht.

    Muss ich zum automatischen Löschen von verknüpften Datensätzen noch etwas tun?

    Mfg Murdoc
    Gruß Murdoc

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

    Das klappt aber leider nicht.
    Was wird dabei angeleiert und bei welcher Fehlerzeile geschieht es?

    Ich würde es immer so machen:
    Immer zuerst die untergeordneten Einträge löschen und dann die Row der übergeordneten Tabelle!
    Es geht aber auch anders herum:
    Kommt darauf an, wie die Relation zueinander eingestellt ist...
    Product-Table wäre die übergeordnete Parenttable und hat eine untergeordnete Tabelle:

    VB.NET-Quellcode

    1. For i = SampleDts.Product.Rows.Count - 1 To 0 Step -1
    2. SampleDts.Product.Rows(i).Delete()
    3. Next
    Da werden die Childeinträge mitgelöscht...
    funktioniert nur:
    *) immer von hinten weg löschen...
    *) wenn die Relation nur als Beziehung eingestellt ist...
    *) mit Beziehungs- und Fremdschlüsseleinschränkung und die Löschregel auf Kaskade eingestellt ist
    Sonst immer zuerst die untergeordneten Einträge löschen und dann die Parentzeile!

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

    Wenn die Relation richtig gesetzt ist, werden die ChildRows mit der ParentRow automatisch mitgelöscht.
    @VB1963: Warum erst die ChildRows, dann die ParentRow? Welche praktischen Vorteile hat dies. Dass Du es so machst, ist mir klar, aber das Warum fehlt mir noch.
    Bilder
    • BeforeAndAfterRemovingParent.png

      23,32 kB, 826×385, 139 mal angesehen
    • Relation.png

      26,1 kB, 1.053×625, 145 mal angesehen
    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 teste mal das Beispiel von VB1963.

    Anonsten schau ich mir morgen noch einmal den Code an wenn ich frisch bin. Wahrscheinlich seh ich den Wald vor lauter Bäumen nicht :whistling:

    Die Beziehung stimmt soweit. Da du ja bestätigst das es (wenn man es richtig macht) funktioniert, liegt der Fehler irgendwo anders bei mir.
    Gruß Murdoc

    VaporiZed schrieb:

    aber das Warum fehlt mir noch.
    Wenn du die Löschregel nicht hättest, bekommst bestimmt eine InvalidConstraintException mit folgendem Text:
    Zusätzliche Informationen: Diese Zeile kann nicht gelöscht werden, da für die Beziehung FK_..._... Einschränkungen erzwungen werden, und das Löschen dieser Zeile untergeordnete Zeilen freilegen würde.
    Und wenn es ginge, dann gäbe es elternlose Kindzeilen...
    D.h. dass der Knackpunkt die richtige Einstellung der Löschregel ist. Also auch auf Cascade stellen - wie in meinem Screenshot, richtig? Oder hab ich's immer noch nicht voll erfasst?
    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.
    Hallo zusammen,

    da ich gerade auch am Datensatzlöschen mit Untertabellen bin, hole ich den alten Beitrag mal kurz wieder hoch.

    In einem kleinen Testprojekt gibt es eine Tabelle Personen und Teleonnr. Telefonnr hat ein Feld für PersonenID und ist auch als Beziehung Personen.ID --> Telefonnr.PersonenID verbunden. (siehe auch Foto von VaporiZed)

    Das löschen mache ich aktuell auch mit

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Btn_Loeschen_Click(sender As Object, e As EventArgs) Handles Btn_Loeschen.Click
    2. ' Bevor der aktuelle Datensatz gelöscht wird, muss noch eine Sicherheitsabfrage beantwortet werden
    3. If MsgBox("Sie sind gerade dabei, den Datensatz" & vbCrLf & vbCrLf &
    4. Me.VornameTextBox.Text & " " & Me.NachnameTextBox.Text & vbCrLf & vbCrLf &
    5. "zu löschen." & vbCrLf & vbCrLf &
    6. "Wenn Sie jetzt auf Ja drücken, dann sind auch alle anderen Daten in den untergeordneten Tabellen nicht mehr nutzbar bzw. vorhanden.", MsgBoxStyle.DefaultButton2 + MsgBoxStyle.YesNo) = MsgBoxResult.No Then
    7. ' wurde diese verneint, dann wird hier abgebrochen und alles bleibt so wie gehabt.
    8. Exit Sub
    9. Else
    10. ' andernfalls wird der aktuelle Datensatz gelöscht
    11. ' Durch die eingestellten Beziehungen der einzelnen Tabellen, werden auch hier die Inhalte der Untertabellen mit gelöscht.
    12. ' Dadurch entstehen keine verweisten Datensätze und die Datenbank wird nicht zugemüllt.
    13. PersonenBindingSource.RemoveCurrent()
    14. End If
    15. End Sub


    Das Ganze funktioniert auch super.

    In meinem späteren Großprojekt gibt es aber x Tabellen die natürlich auch mit diversen Tabellen verbunden sind.

    Es soll eine Stammdatentabelle geben, in denen alle Artikelgrunddaten drin stehen.
    Danach gibt es für einige Eingabemasken die passenden Tabellen die mit der Stammdatentabelle verbunden sind.
    Die Eingabemaskentabellen haben nun Beziehungen zu Tabellen, die bzw. nur für diesen Artikel Informationen sammeln (Tabelle Belege bspw.), Dann gibt es aber für einige Felder auch Untertabellen, die nur eine Informationsauswahl liefern (Hersteller, Herkunftsadresse usw.) Diese Tabelleninhalte gelten somit auch noch für andere Datensätze.

    Fazit: Solange der aktuelle Stammdatensatz in den anderen Tabellen einmalig ist (Es kann zwar mehrere Belege für einen Artikel geben, wenn man diesen mehrmals gekauft hat), muss die Beziehung zwischen den Tabellen so aussehen wie oben beschrieben. Bei den Informations-Untertabellen reicht eine normale Beziehung aus oder brauche ich hierfür gar keine Beziehung. Das Auswählen und das Abspeichern des ID Wertes einer Untertabelle bräuchte doch keine Beziehung, da ich doch in den Eigenschaften des Anzeigecontrols die Tabelle und die Anzeige- bzw. Wertefelder einzeln auswähle.

    Ich habe es gerade mal getestet: Es klappt beides. Mit oder ohne Beziehung zu den Informationstabellen. Beim Löschen werden also nur die Datentabellen gelöscht, die mit Descade in der Beziehung eingestellt sind.

    Liege ich mit meiner Darstellung und Annahme richtig oder gibt es hier doch noch etwas zu beachten, was ich jetzt nicht bedacht habe? Über eine kurze Rückmeldung würde ich mich sehr freuen.

    Gruß

    Volker
    Hallo zusammen,

    das mit dem Extrafeld habe ich tatsächlich schon ins Auge gefasst und auch in die Stammdatentabelle eingebaut.

    Grund war tatsächlich, dass man sehr schnell alle Daten verliert. Es ist zwar sehr praktisch, dass auch alle mit Beziehungen ausgestattete Tabellen gleich mit gelöscht werden, aber falsch man da sich doch mal vertan hat, ist halt auch alles sehr schnell weg.

    @Coldfire: In erster Linie m.M.n. natürlich der Benutzer. Der gibt ja den Befehl an das Programm. Das Programm führt dann nur die Aktionen richtig aus. Die Datenbank hält dann nur den aktuellen Stand fest. Das gleiche ist ja auch, wenn Du direkt in der Datenbank Datensätze löscht.

    Schönen Wochenstart

    Volker
    Hallo Kasi,

    DAU ist gut, was ist aber, wenn der DAU auch gleich Programmierer ist?

    Werde wohl aktuell den Datensatz nur inaktiv setzen. Am Ende könnte man ja immer noch eine Löschaktion über die inaktiven Datensätze ausführen. Vielleicht sogar mit einem vorherigen Bericht aller Daten, die gelöscht werden. Aber das ist dann ein anderes Thema.

    Gruß
    Volker