Aktualisierung Dataset

  • VB.NET

Es gibt 55 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Aktualisierung Dataset

    Hallo Zusammen,

    einleitend noch ein gesundes Neues!

    Nun zu meinem Anliegen, ich habe ein Auftragsbuch mit einem DGV, einer Bindingsource sowie einem Dataset.
    Mit einer Eingabemaske wird alles eingetragen und am Schluß in einer XML gespeichert.
    Soweit funktioniert das auch alles.
    Jetzt möchte ich das Programm auf einem zweiten Rechner laufen lassen und natürlich auch gemachte Änderungen aktualisiert abbilden.
    Leider kollidiert das irgendwie mit dem AutoIncrement. Er macht bei ienem Neueintrag nicht mit der Folgenummer weiter, sondern generiert eine willkürliche Nummer.

    Diverse Recherchen haben immer wieder auf einen TableAdapter hingewiesen. Nur habe ich einen solchen nicht in meinem Projekt und wüsste jetzt auch nicht wie ich den einbauen soll.

    Vielleicht habt ihr ja eine Lösung für mich.

    Grüße

    *Topic verschoben*

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

    Wenn zwei Programminstanzen laufen, hat jedes für sich zu Programmstart die Daten, die in der Datei stehen. Nach Programmstart werkelt jede Proramminstanz für sich weiter. Ein Fortsetzen der AutoIncrement-ID kann eigentlich nur dann bei diesem Szenario erfolgreich sein, wenn nach Neuerstellung einer TableRow die Daten gleich in der XML abgespeichert werden und die andere Programminstanz per FileSystemwatcher diese Änderung mitbekommt und dann die Daten neu einliest. Oder ist die "Kommunikation" zwischen Datenpersisierung in Programm anders?
    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.

    Madde schrieb:

    Jetzt möchte ich das Programm auf einem zweiten Rechner laufen lassen und natürlich auch gemachte Änderungen aktualisiert abbilden.
    Verstehe ich nicht.
    Wie kommen die Daten von einem Rechner auf den anderen?

    Madde schrieb:

    Diverse Recherchen haben immer wieder auf einen TableAdapter hingewiesen.
    Dazu müsstest du statt in eine Xml in eine Datenbank schreiben.

    ErfinderDesRades schrieb:

    Verstehe ich nicht.
    Wie kommen die Daten von einem Rechner auf den anderen

    Das Proggy liegt auf einem Netzlaufwerk und ist als Verknüpfung auf Rechner X hinterlegt. Rechner Y soll nun ebenfalls das Programm am laufen haben.

    Einträge sollen nur auf Rechner X erfolgen, Rechner Y soll aber halt die Aktualisierungen mitbekommen.

    VaporiZed schrieb:

    …wenn nach Neuerstellung einer TableRow die Daten gleich in der XML abgespeichert werden und die andere Programminstanz per FileSystemwatcher diese Änderung mitbekommt und dann die Daten neu einliest…

    Das hört sich nach einer Lösung an. Mal schauen, wie ich das umgesetzt bekomme.
    Dassisjalustig!

    Genau sowas habich gestern für mein Stechuhr-Programm implementiert. Ist einiges zu beachten:
    • Einen Fsw ziehste aus der Toolbox aufs Form.
      Andernfalls bekommst du Threadübergreifende Control-Zugriffe mit den anhängigen Exceptions
    • Dann brauchste noch einen Delay-Timer, weil der Fsw immer mindestens zweimal feuert, aber du willst die Daten ja nur einmal reloaden.
    • Dann musste noch dran denken, beim Speichern das Fsw_Change-Event temporär zu deabonnieren, sonst reloaded deine eigene Anwendung den Kladderadatsch ja auch nochmal, obwohl sie ihn doch grade weggeschrieben hat.
    Also hier paar Snippets dazu:

    VB.NET-Quellcode

    1. Public Sub FormLoad(...)
    2. 'Fsw konfigurieren
    3. Fsw.Path = Dts.DataFile().DirectoryName
    4. Fsw.Filter = Dts.DataFile().Name
    5. Fsw.NotifyFilter = NotifyFilters.Size ' Size als NotifyFilter reicht
    6. End Sub
    7. Private Sub Fsw_Changed(sender As Object, e As FileSystemEventArgs) Handles Fsw.Changed
    8. 'jedesmal den Delay-Timer (Intervall=1500) restarten. Erfolgt das schnell hintereinander, so wird der Reload trotzdem nur einmal ausgeführt
    9. timDelay.Stop()
    10. timDelay.Start()
    11. End Sub
    12. Private Sub timDelay_Tick(sender As Object, e As EventArgs) Handles timDelay.Tick
    13. 'ein sog. 'One-Shot-Timer'
    14. timDelay.Stop()
    15. Reload()
    16. End Sub
    17. Private Sub Save()
    18. '...
    19. RemoveHandler Fsw.Changed, AddressOf Fsw_Changed 'verhindern, dass das Save ein Selbst-Reload auslöst
    20. Dts.Adapter.Save(Me, checkForChanges)
    21. AddHandler Fsw.Changed, AddressOf Fsw_Changed
    22. End Sub

    @ErfinderDesRades Erstmal Danke für Dein Beispiel. Mit zwei Sachen komme ich noch nicht klar.

    ErfinderDesRades schrieb:

    Fsw.Path = Dts.DataFile().DirectoryName
    Fsw.Filter = Dts.DataFile().Name

    Hier kann ich ja nur einen "festen" Pfad festlegen, richtig? Die zu überwachende Datei befindet sich im gleichen Verzeichnis wie die Programmdatei. Wie muss ich das eintragen?

    Zweiter Punkt ist ein Fehler beim Reload- @ErfinderDesRades - hier habe ich Deinen Code aus anderen Projekten verwendet.

    VB.NET-Quellcode

    1. Private Sub Reload()
    2. DtsAuftragsbuch.Clear()
    3. For Each tb As DataTable In DtsAuftragsbuch.Tables
    4. tb.BeginLoadData() 'deaktiviert während des Ladens AktualisierungsVorgänge des Databindings
    5. Next
    6. DtsAuftragsbuch.ReadXml(_DataFile.FullName)
    7. For Each tb As DataTable In DtsAuftragsbuch.Tables
    8. tb.EndLoadData()
    9. Next
    10. DtsAuftragsbuch.EnforceConstraints = True 'tb.BeginLoadData setzt autom. EnforceConstraints.False - also zurücksetzen
    11. DtsAuftragsbuch.AcceptChanges()
    12. End Sub

    Hier kommt (bei Zeile 6) der Fehler, die Datei wird von einem anderen Prozess verwendet.

    Grüße

    Madde schrieb:

    Hier kommt der Fehler, die Datei wird von einem anderen Prozess verwendet.

    Da solltest Du grundsätzlich mal dem Neueinlesen eine Pause von ca. 3 Sekunden vorsetzen. Denn das Schreiben und Freigeben der XML von Prog1 kann etwas dauern. Wenn das klappt, dann kannst Du auch statt der 3-Sekunden-Wartezeit ne Delay-Schleife einbauen, in der z.B. 5x alle 0,5 Sekunden getestet wird, ob der Zugriff auf die Datei möglich ist. Wenn Deine genannte Exception kommt, dann eben nochmal warten, ansonsten Datei auslesen und Delay-Schleife verlassen.

    Madde schrieb:

    Die zu überwachende Datei befindet sich im gleichen Verzeichnis wie die Programmdatei
    Nutze Application.StartupPath
    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.
    Ok, der Zugriffsfehler ist mit timDelay.Interval = 1500 jetzt weg.

    Leider ist das Grundproblem, dass die ID nicht weitergeführt, sondern willkürlich gewählt wird, immer noch präsent.
    Irgendwo mache ich wohl noch Fehler.

    Auch verstehe ich die Zeile dts.Adapter.Save(Me, checkForChanges) nicht. Was muss ich hier denn verwenden?

    Grüße

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

    Bei der dts.Adapter.Save-Zeile kann ich nicht weiterhelfen. Ich vermute, dass das was mit TableAdaptern zu tun hat, die Du eh nicht in Deinem Projekt hast.
    Das mit der ID versteh ich insofern nicht, weil doch die 2. Programminstanz nur lesen soll und keine eigenen TableRows erstellt. Oder hab ich da was falsch verstanden? Oder tritt das ID-Problem allein in der ersten ProgInstanz auf? Was heißt eigentlich willkürlich? Reihenfolge bei Erstellung ist -1, 58, 666, -42, 513? Was passiert, wenn Du nur eine Instanz zu laufen hast und da mal das in-die-Datei-zwischenspeichern weglässt? Hast Du bei der 1. ProgInstanz den FSW deaktiviert?
    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.
    So, also ich hatte 2 Programminstanzen mit gleichem Code laufen, das funktioniert nicht.
    Die Clientversion ist nun mit dem Filesystemwatcher ausgestattet und die Serverversion läuft ohne den Zusätzen. Das würde einwandfrei laufen, bringt mich aber, bei den nachträglichen Überlegungen nicht weiter.
    Leider habe ich nicht bedacht, dass wenn in der Clientversion ein Haken bei "erledigt" gesetzt wird, dies natürlich auch in der Serverversion dargestellt werden sollte.
    Also doch Änderungen auf beiden Seiten.
    Einziger Unterschied ist, in der Clientversion sollten nur bereits bestehende Zeilen änderbar sein, Neueinträge sind nicht möglich.
    Sowie aber Änderungen jeglicher Art in der Clientversion vorgenommen werden, kommt bei ienem Neueintrag in der Serverversion eine willkürliche Nummer.
    Nach was für einem Muster diese gewählt wird, kann ich nicht sagen, das ist für mich nicht erkennbar.
    Der letzte Eintrag ist die 3976 und er will als nächstes mit der 7218 weitermachen und wenn ich dann eine Änderung in der Clientversion vornehme, macht er mit der 10459 weiter.
    Einzig die Tatsache, wenn ich die Instanzen schließe und das Prozedere genau so wiederhole, sind die willkürlichen Nummer identisch, also auch wieder die 7218 sowie 10459.

    Bekomme ich das mit der ID irgendwie umgesetzt?

    Grüße

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

    Also zunächstmal: meine Snippets aus post#5 kannste nicht einfach bei dir einpasten.
    Die illustrieren nur, was ich in prosa dazu-schrieb, wie vorzugehen ist. Also im Form_Load (oder sonst einer Startup-Methode) ist was zu machen, in Fsw_Changed, im timDelay_Tick und beim Saven.

    Was im einzelnen zu machen ist, kann ich nicht vorgeben - ich habe ja ein anderes Dataset und verwende vermutlich andere Load/Save - Methoden.
    Vermutlich sehr andere Methoden, weil bei mir leere ich das dataset und lese es komplett neu ein - unterschiedliche Ids können da nicht auftreten.

    Jetzt sprichst du aber auchnicht von geänderten Ids, sondern vom Id-Seed, also dem generierten Id-Wert bei Neuanlagen.
    Kann sein, dass das bei mir auch so ist, muss ich mal gucken.
    Die Funktionsfähigkeit sollte daa aber nicht beeinträchtigen.

    Du kannst, wenn du das Dataset komplett geleert hast, für alle AutoIncrement-Spalten aller Tabellen Increment_Seed=1 einstellen, bevor du reloadest. Vielleicht hilft das.
    Increment_Seed heisst in Wirklichkeit iwie anders, bin ich jetzt zu faul, nachzugucken. Ist aber eine Eigenschaft der DataColumn.

    ErfinderDesRades schrieb:

    Also zunächstmal: meine Snippets aus post#5 kannste nicht einfach bei dir einpasten.
    Nein das ist mir natürlich bewusst. Die Adaptersache hatte ich bereits auskommentiert, da ich das nicht kannte. Ich bin halt leider kein Programmierer der richtig tief in der Materie steckt, um alles richtig zu deuten.

    ErfinderDesRades schrieb:

    Vermutlich sehr andere Methoden, weil bei mir leere ich das dataset und lese es komplett neu ein - unterschiedliche Ids können da nicht auftreten.

    Ich dachte mein Dataset wird im Reload-Teil mit diesem Code geleert und wieder neu befüllt?!

    Quellcode

    1. DtsAuftragsbuch.Clear()
    2. For Each tb As DataTable In DtsAuftragsbuch.Tables
    3. tb.BeginLoadData() 'deaktiviert während des Ladens AktualisierungsVorgänge des Databindings


    Der Tipp mit IncrementSeed vor dem Reload bring mich leider auch nicht zum Ziel.
    DtsAuftragsbuch.tblAuftragsbuch.AuftrNrColumn.AutoIncrementSeed = 1 hat nichts bewirkt.
    jetzt habich mal probiert.

    Bei mir wird der Seed auf den niedrigsten sinnvollen Wert gesetzt.
    Ist in meiner Anwednung der Seed auf 30 und ich reloade eine Dataset-Datei, bei der 5 Datensätze hinzukamen, so geht mein Seed auf 36 (30+5+1).
    reloade ich eine Dataset-Datei, bei der die höchsten 5 Datensätze gelöscht wurden, so bleibt mein Seed dennoch auf 31 - obwohl theoretisch auch ein Seed von 26 technisch möglich wäre.

    Es passiert aber nicht, dass mehrere Reloads derselben Dataset-Datei den Seed immer verdoppeln oder sowas.
    Guten Morgen,

    ich komme leider nicht zum Ziel.

    Sowie der Reload gestartet wird, wird die ID "wild" weitergeführt. Ich weiß auch nicht, wo ich ansetzen soll.
    Den Seed-Befehl habe ich direkt mit in den Reload nach dem Clear gesetzt.
    Du schriebst in Post#11 davon, dass es auch weiterer Dinge bedarf in Fsw_Changed und timDelay_Tick, als die von Dir in deinem Code dargestellten Befehle.
    Vielleicht liegt ja hier das Problem bei mir.

    Vielleicht könnte mir nochmal unter die Arme gegriffen werden.

    Grüße
    Lass Dir doch mal alle IDs anzeigen. Vielleicht sind ja mehr Daten im tDS als erwartet.
    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.
    Vor dem Speichern, nach dem Speichern, vor dem Laden, nach dem Laden und nach dem Auftreten der unsinnigen nächsten ID mal bitte jeweils das hier ausführen und Werte notieren/hier posten

    VB.NET-Quellcode

    1. Dim RowCount = DeinTds.DeineDataTable.Count
    2. Dim MinID = DeinTds.DeineDataTable.Min(Function(x) x.ID)
    3. Dim MaxID = DeinTds.DeineDataTable.Max(Function(x) x.ID)
    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.
    So, ich habe nun ein Muster erkennen können.

    Bei einem Neueintrag werden zu der Folge-ID alle Zeilen hinzu addiert.
    Letzte ID ist 10, nächste wäre 11, ist aber die 21. 11 + die 10 Zeilen.

    Ich habe die Tests mit über 4000 Einträgen gemacht, was dumm war, da ich das Problem so nicht gleich sehen konnte.

    Warum das so ist, weiß aber nicht, da hoffe ich auf Euer Wissen.
    Hm. Leider fehlen jetzt die gewünschten Kennzahlen. Vor allem RowCount ist interessant.
    Die nächste Frage, die Du Dir stellen solltest, ist: Wieviele Rows hat vor und nach jeder der genannten Aktionen Deine DataTable.
    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.
    Folgende Kostellationen

    Neustart - Folgenummer korrekt
    Neueingabe - Folgenummer mit genannter Addition der Zeilen
    Einen Unterschied vor und nach dem Speichern gibt es wohl nicht.

    Die Gesamtzahl der Rows wird korrekt ausgelesen, nur eben die IDs werden immer wieder hochgezählt. Habe einen Reload Button zum testen verwendet. So oft wie ich reloade, so oft wird die Gesamtzahl der Zeilen zur ID addiert.
    Bilder
    • dgv.JPG

      24,75 kB, 220×273, 62 mal angesehen