Dataset->Db und nicht immer alle Tabellen speichern

  • VB.NET
  • .NET 4.5

Es gibt 31 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

    Dataset->Db und nicht immer alle Tabellen speichern

    Ich arbeite mit Dataset->Db. Mit .SaveDts() stoße ich das Speichern aller Änderungen (in allen allen Tabellen) im DataSet an.

    Das Speichern von Änderungen einzelner Tabellen scheint nicht möglich zu sein, was ich erstmal auch verstehe, da so wohl eine mögliche Inkonsistenz des Datenbestandes verhindert werden soll.

    Mein Problem ist nun folgendes:
    Ein Teil meiner Anwendung schreibt automatisiert Daten in die Datenbank; legt also Rows an, füllt diese mit Daten und speichert diese danach durch Aufruf von .SaveDts() in der Datenbank.
    Zeitgleich werden an anderer Stelle in meiner Anwendung beispielsweise Datensätze (von Tabellen, die mit der anderen in keinem Zusammenhang stehen) verändert. Diese Änderungen sind in bestimmten Fällen noch nicht abgeschlossen, wenn der andere Prozess die Speicherung anstößt. Dann werden Daten (mit)gespeichert, die so nicht in der Datenbank sein sollen.

    Bestimmt hat sich darüber schon mal jemand Gedanken gemacht :)

    Mir fallen dazu drei Möglichkeiten ein:

    1.
    Die Tabellen auf zwei DataSets aufteilen

    2.
    Die Modifikation der Datensätze so gestalten, daß keine halbfertigen Datensätze in den Tabellen sind

    3.
    Eine Erweiterung des Dataset->Db-Projektes, so daß es möglich ist einzelne Tabellen zu speichern, wobei dann aber auch (der Datenkonsistenz wegen) Tabellen mit Anhängigkeiten zu dieser ebenfalls gespeichert werden. Zu welchen Tabellen Abhängigkeiten bestehen, weiß Dataset->Db.

    Resümee:
    1. würde das Handling insgesamt erschweren
    2. würde an einigen Stellen das schlanke Arbeiten mit wenig Code erschweren
    3. wäre die top Lösung.

    Gibt es 3. eventuell schon und ich habe das nur nicht gefunden?
    --------
    Lieber inkompetent als inkontinent

    100Volt schrieb:

    1. würde das Handling insgesamt erschweren

    was soll das bewirken Tabllen auf 2 Datasets aufzuteilen?

    100Volt schrieb:

    2. würde an einigen Stellen das schlanke Arbeiten mit wenig Code erschweren

    wie soll die prüfung lauten?

    100Volt schrieb:

    3. wäre die top Lösung.

    versteh' ich nicht. ein dataset ist doch pro user im arbeitsspeicher des pc's gefüllt.
    Wenn du an Rechner a) automatisiert Datenanlegst, speicherst du doch nicht den angefangenen Datensatz von Rechner b) weil der ist ja noch in Bearbeitung - oder wenn es ein neuer ist, dann ist der ja sogar
    DatarowState.Detached -> wird also nicht persistiert in dem Zustand.

    Also für neu ist's eine Detached-Row, beim Editieren bleibt der originale Datensatz erstmal im Urpsrungszustand, bis der User auf speichern drückt (oder in meinem Fall den Edit-Dialog Closed, dann wird automatisch gespeichert.)
    Denn erst NACH dem Edit ist die Row im Modified-Rowstate. Den Rest macht die Datenbank (wenn du hier angst vor Überschneidenden ID's hast)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    100Volt schrieb:

    Ein Teil meiner Anwendung schreibt automatisiert Daten in die Datenbank; legt also Rows an, füllt diese mit Daten und speichert diese danach durch Aufruf von .SaveDts() in der Datenbank.
    Zeitgleich werden an anderer Stelle in meiner Anwendung beispielsweise Datensätze (von Tabellen, die mit der anderen in keinem Zusammenhang stehen) verändert. Diese Änderungen sind in bestimmten Fällen noch nicht abgeschlossen, wenn der andere Prozess die Speicherung anstößt. Dann werden Daten (mit)gespeichert, die so nicht in der Datenbank sein sollen.
    Wie können diese MassenOperationen zeitgleich erfolgen?
    Bist du da mit MultiThreading unterwegs?
    Das kann an noch ganz anderen Stellen sehr problematisch werden, weil Databinding mit MultiThreading nicht funktioniert.

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

    @tragl:
    was soll das bewirken Tabllen auf 2 Datasets aufzuteilen?

    Damit bei .SaveDts nur ein Teil der Tabellen, nämlich die im jeweiligen DataSet, in die DB geschrieben/aktualisiert werden.


    wie soll die prüfung lauten?

    Der Hilfsprojektcode (so nenne ich den mal) liest doch bei der Initialisierung die Infos aus dem DataSet ein, also Tabellen und Relationen. Damit "weiß" der Code was zusammen gespeichert werden muß, damit es nicht zu Inkonsistenzen im Datenbestand kommt.


    versteh' ich nicht. ein dataset ist doch pro user im arbeitsspeicher des pc's gefüllt.
    Wenn du an Rechner a) automatisiert Datenanlegst, speicherst du doch nicht den angefangenen Datensatz von Rechner b)...

    Ich meine die selbe Instanz der Anwendung.

    DatarowState klingt erstmal interessant. Darf mein Code denn diese Eigenschaft verändern?


    Würde hier automatisch während der Zeit zwischen den Aufrufen von Sub1 und Sub2 die DataRow rowKunden auf DatarowState.Detached gesetzt werden? ..und bei einem DataRow-Array alle DataRows des Arrays?

    VB.NET-Quellcode

    1. Private rowKunden As KundenRow
    2. Private Sub Sub1()
    3. Dts.Kunden.CustomFill("")
    4. rowKunden = Dts.Kunden.FirstOrDefault(Function(x) x.ID = 815)
    5. rowKunden.Vorname = "Sarah"
    6. End Sub
    7. Private Sub Sub2()
    8. rowKunden.Nachname = "Lolamann"
    9. Dts.SaveDts()
    10. End Sub



    @EdR:
    Wie können diese MassenOperationen zeitgleich erfolgen?
    Bist du da mit MultiThreading unterwegs?
    Das kann an noch ganz anderen Stellen sehr problematisch werden, weil Databinding mit MultiThreading nicht funktioniert.

    Teilweise ja. Guter Hinweis, danke!
    Es gibt Events, die zu Änderungen in den Tabellen führen.

    Dann mache ich die automatisierten Operationen besser separat, also ohne Nutzung des DataSet->Db-Codes. Das wäre vom Effekt her dann so, als hätte es ein ganz anderer User/Anwendungsinstanz gemacht.
    --------
    Lieber inkompetent als inkontinent

    100Volt schrieb:

    Dann mache ich die automatisierten Operationen besser separat
    Du könntest sogar erwägen, die Operationen in eine eigene Anwendung auszulagern.
    Oder gar eine zweite Datenbank verwenden.
    Wenn die Dinge wirklich sooo unabhängig voneinander sind gibts vlt. gar keinen Grund, das in derselben Anwendung zu programmieren.
    Sooo unabhängig ist es insgesamt betrachtet nicht. Es müssen sich häufig ändernde Infos in der vom Anwender bedienten Anwendung visualisiert werden. Über eine separate (Hintergrund)Anwendung hatte ich kurz nachgedacht, aber dann müßte ich die Infos irgendwie zwischen den Anwendungen austauschen. Via DB würde das wohl gehen und sogar weitere Vorteile bieten, aber wenn ich beispielsweise im 3-Sekundentakt Infos reinschreibe, genauso oft auslese (im worst-case dann schon knapp sechs Sekunden alte Daten habe), erzeuge ich viele Datenbankzugriffe. Wenn das dann noch von vielen Orten/PCs aus passiert, wird der Webhoster, auf dessen Server die DB liegt, vielleicht rebellisch.
    --------
    Lieber inkompetent als inkontinent

    100Volt schrieb:

    Würde hier automatisch während der Zeit zwischen den Aufrufen von Sub1 und Sub2 die DataRow rowKunden auf DatarowState.Detached gesetzt werden?
    Tja, offsichtlich haste da eine etwas eigenwillige DB-Anwendung am Hals.
    Das kann DbPersistance wahrscheinlich unmodifiziert nicht alles abdecken, was du brauchst.
    Wäre für mich aber auch nur mässig sinnvoll, da jetzt allerlei Sonderlocken drin einzubauen und so die Komplexität von DbPersistance weiter zu erhöhen - was bis auf dich kaum je einer brauchen wird, und wo dann auch niemand mehr durchblicken kann.
    Ich denke derzeit über einen Refresh-Mechanismus nach, also dass eine Abfrage wiederholt werden, aber ich fürchte, da wird auch wieder sowas von Komplexität-Monster bei rauskommen, sodass man DbPersistance nicht mehr verstehen kann, und ggfs. problembezogen modifizieren.
    Aber vilt kann man das ja bereits jetzt schon nicht mehr :/
    Naja, wenn man die Eigenarten vorher kennt, kann man ja um die Probleme drumherum programmieren :)

    Refresh-Mechanismus klingt gut. Mit Events?

    Bzgl. Komplexität und Verständlichkeit:
    Dein Code ist sehr schlank, optimiert, komprimiert. Das ist (für mich) gar nicht einfach zu verstehen.
    Was mir sehr schwer fiel, war die Orientierung zwischen den ganzen Helpers-Projekten, die Du im Laufe der Zeit geschrieben hast. Man muß sich durch viele alte Beiträge lesen um das halbwegs zu verstehen.
    Eigentlich hast Du schon fast eine potentiell kommerzielle Komponente geschaffen. Da fehlt "nur" noch die Doku! :)
    Denn ansonsten sind die Sachen von Chilkat und so auch nicht toller, nur halt nicht gratis.

    Aber was ist denn bzgl. der Antwort zum Zitat aus Post #7? Ja oder nein?
    --------
    Lieber inkompetent als inkontinent
    Ups, da habich zwei antworten geschrieben, und eine halb gelöscht.
    Also Antwort: Nein.

    In deim Code kommt eine Detached Row ühaupt nicht vor.
    Guck MS-Doku: docs.microsoft.com/de-de/dotne…datarowstate?view=net-5.0
    Kurz: detached Rows sind eiglich unmögliche Rows, die iwo herumfliegen, und in keiner DataTable enthalten sind.

    Detached Rows entstehen nur auf 2 Weisen:
    1. dim rwMy = myDataTable.NewMyRow()
      wovon abzuraten ist, weil Gefahr besteht, notwendige Spalten nicht zu befüllen. Besser ist:
      dim rwMy = myDataTable.AddNewMyRow(arg1, arg2,...) - diese rwMy ist ausserdem nicht detached, sondern ist bereits added - was ein Vorteil ist.
    2. Im DGV die Zufüge-Zeile - die ist an eine detached Row gebunden, und sorgt bei rumhühnern im DGV auch immer gerne für unangenehme Überraschungen.
    ok, danke!

    Dann verwendete ich ausschließlich dim rwMy = myDataTable.AddNewMyRow(arg1, arg2,...).
    Die erste Variante finde ich so schön übersichtlich, mir Feld für Feld einzeln vorzuknöpfen, aber (weitere) Probleme brauche ich nicht, deswegen jetzt Finger weg! :)
    --------
    Lieber inkompetent als inkontinent
    Übersichtlich gestalten und einzeln vorknöpfen kann man auch mit AddMyRow, und ist dank Intellisense und benannter Parameter eiglich nicht mehr Arbeit - guck:

    VB.NET-Quellcode

    1. Dim rwBestellg = Dts.Bestellung.AddBestellungRow(
    2. Nr:=Nothing,
    3. Datum:=Nothing,
    4. parentBestellStatusRowByFK_BestellStatus_Bestellung:=Nothing,
    5. Ansprechpartner:=Nothing,
    6. Lieferadresse:=Nothing,
    7. parentStandortRowByFK_Standort_Bestellung:=Nothing)
    Nun kannste vorknöpfen

    VB.NET-Quellcode

    1. Dim rwBestellg = Dts.Bestellung.AddBestellungRow(
    2. Nr:=Nothing,
    3. Datum:=Nothing,
    4. parentBestellStatusRowByFK_BestellStatus_Bestellung:=Nothing,
    5. Ansprechpartner:=Nothing,
    6. Lieferadresse:=Nothing,
    7. parentStandortRowByFK_Standort_Bestellung:=Nothing)
    8. Select Case 4
    9. Case 3 : rwBestellg.Ansprechpartner = "33"
    10. Case 4 : rwBestellg.Ansprechpartner = "44"
    11. End Select

    ErfinderDesRades schrieb:

    Wäre für mich aber auch nur mässig sinnvoll, da jetzt allerlei Sonderlocken drin einzubauen und so die Komplexität von DbPersistance weiter zu erhöhen


    Vielleicht sollten wir (ich helf' da gerne bei) so eine Art Erweiterung für die Persistance entwickeln -> also die Persistance wie sie jetzt ist, so belassen und eine Art Zusatzmodul dafür häkeln.
    Die Persistance und auch DataSetOnly funktioniert sehr gut - wenn es um eine Einzelanwender-Lösung geht.
    Sobald hier ich nenn's mal MultiUser-Betrieb in Betracht kommt muss man entweder an jeder stelle komplexen Kauderwelsch programmieren oder man muss damit leben, dass man ggf. inkonsistenz in den Daten hat.

    Bei meiner Anwendung z.B. wäre es ja auch notwendig, dass in bestimmten Situationen der einzelne Datensatz mit allen über- und untergeordneten Datensätzen (nicht die ganzen Tabellen) neu geladen wird -
    und / oder dass Daten gemerged werden etc. Dazu wär's wie ich schon sagte auch schön, dass man bei z.B. Anwendungsstart oder beim Öffnen einer Form die benötigten Daten in's DataSet lädt und solange die Form geöffnet ist,
    gilt eben dieser geladene Datenstand für die Ansicht - egal was im Hintergrund sonst noch passiert ist. Will der User dann was mit einem der Datensätze tun, muss eine Prüfung stattfinden:
    - wurde der Datensatz gelöscht: Meldung an User
    - wurde der Datensatz von jemand anderem in der Zwischenzeit geändert: aktuellen Datensatz mit Parents/Childs aus DB in's DataSet ziehen und anzeigen
    - ist der Datensatz unverändert: nix tun

    Die "Bequemlichkeit": ich ändere in Tabelle Objekt einen Datensatz und die Änderung wird mir automatisch in der Form Kunde angezeigt ist nur was für Single-User - bei Multiuser klappt das nicht.
    Ich sehe sowas absolut in einer Erweiterung. Und Programmierer, die sowas brauchen sollten im Vorfeld den "einfachen" weg ja schon beschritten haben.

    @100Volt: steht denn tatsächlich nur ein Rechner mit der Anwendung an jedem Standort oder können das auch mal mehrere sein?
    Wenn's mehrere sind, dann solltest du eine Art Server-Backend schreiben, was sich pro Standort um die automatisierung kümmert - sonst wird das ja bei jedem User an dem jeweiligen
    Standort ausgeführt, der die Anwendung öffnet. Dann haste alles doppelt und dreifach in der Datenbank, wird ja auch nicht die Lösung sein. Ansonsten wenn's wirklich nur ein Rechner ist
    käme mein Wunsch von oben ja auch hier zum Tragen (wäre ja quasi multiuser: einmal automatisch über Code und einmal manuell über die GUI)

    Edit: Dazu gehört natürlich auch ein sauber funktionierendes RecordLocking - ggf. könnten wir auf diese Weise die Klassen von Hier testen.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    @tragl:
    steht denn tatsächlich nur ein Rechner mit der Anwendung an jedem Standort oder können das auch mal mehrere sein?

    Ja, nur ein PC. Die Meßgeräte (auf deren Software/Firmware habe ich keinen Einfluß) sind im LAN und übermitteln diesem PC ihre Daten.


    @Kasi:
    Den Artikel hatte ich im Rahmen meiner Recherchen schon mal gelesen. Er ist von MS über SQL Server. Ich arbeite mit mySQL. Was meine damalige Suche nach einer ähnlichen Funktion bei mySQL ergab, weiß ich allerdings nicht mehr.
    --------
    Lieber inkompetent als inkontinent

    100Volt schrieb:

    @tragl:
    steht denn tatsächlich nur ein Rechner mit der Anwendung an jedem Standort oder können das auch mal mehrere sein?




    @Kasi:
    Ich arbeite mit mySQL. Was meine damalige Suche nach einer ähnlichen Funktion bei mySQL ergab, weiß ich allerdings nicht mehr.


    siehe hier GitHub, aber ob es was taugt kann ich nicht sagen
    [html][github.com/Cyclonecode/mysql-notification/html]
    bleiben noch UDF Function in C++ schreiben, oder auf SQL-Server oder Oracle umzusteigen