Remote SQL Datenbank lokal speichern und bei nicht erreichbarkeit die Lokale Datenbank benutzen

  • VB.NET

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Ostseebengel74.

    Remote SQL Datenbank lokal speichern und bei nicht erreichbarkeit die Lokale Datenbank benutzen

    Hallo

    Ich versuche mal mein Problem zu schildern. (arbeite übrigens mit Visual Studio)

    Mit einem von mir geschriebenen Programm das bereits seit einem Jahr in unserer Firma eingesetzt wird, rufe ich Daten aus einer Remote fähigen SQL Datenbank ab. Dort existieren zur Zeit 5 "Tabellen" mit diversen Informationen der Kunden und Anlagen die wir betreuen.
    Das Auslesen, Löschen Updaten funktioniert alles Perfekt. Ich abe einen MySQLAdapter und diverse DataTables die mit denen ich verschiedene SQL Abfragen an die Datenbank sende und über die DataTables in diverse DGV schreibe.
    Jetzt ist es so ,das unsere Anlagen ofmals in Kellern stehen an denen kein Hotspot mit dem Handy eingerichtet werden kann um das von mir geschriebene Programm zu benutzen.

    Jetzt war mein Gedanke, die komplette SQL Datenbank einzulesen. Das macht das Programm beispielsweise bei einer erfolgreichen Verbindung automatisch und das ganze in 5 XML Files zu speichern.
    Wird das Programm dann ohne Internet Verbindung aufgerufen, switcht es automatisch auf die XML Dateien um und zieht die letzten vorhanden Daten. Der Kollege vor Ort hat dann zumindest die Informationen, die seit der letzten Verbindung verfügbar waren auf dem Rechner und kann damit seine Berichte ausfüllen.

    Ist der Gedankenansatz OK oder gibt es eine andere Möglichkeit? Nice wäre folgendes: Der Kollege ist 1 Woche auf Achse und benutzt ausschließlich die Offline Daten. Beim Abschluß der Arbeitswoche könnte dann eine Syncronisierung seiner XML Daten mit der Remote Datenbank erfolgen.



    Ich hoffe ich konnte mich verständlich ausdrücken



    Zum Testen habe z.B. folgendes Versucht

    die dtable0 enthält ALLE Daten aus der Datenbank "Tabelle" mitarbeiter
    dem Projekt habe ich über Hinzufügen - Neues Element - mitarbeiter.xml zugefügt

    VB.NET-Quellcode

    1. dtable0.WriteXml("mitarbeiter.xml", XmlWriteMode.WriteSchema)


    damit möchte ich eigentlich das die XML mit der dtable0 befüllt wird... funzt leider nicht





    Ich bedanke mich
    Moin Ostseebengel!
    Guck mal nach "Dataset only" hier im Forum. Dann lernst du, wie man mit einem Dataset und Bindingsourcen arbeitet. So ein Dataset kannste komplett in ein XML schreiben, also etwa mit Dataset.SaveXML(). Oder alternativ eine MySQL DB schreiben, dazu guckst du nach "Dataset -> DB".
    Der Trick ist der Zwischenschritt "Dataset". Ich verstehe doch so, dass du unmittelbar auf der SQL-DB herumwurschtelst. Das wirst du wohl ändern müssen ;)

    Viel Spaß!

    Viele Grüße Oliver
    Dachte ich mir ;(

    Onkel Google hat mir das so erklärt...

    Eine DataTable hält die Daten für eine Tabelle, die Per DataAdapter eingelesen wurden.
    Ein DataSet hält verschiedene Tabellen und die Relationen zwischen ihnen.


    Kann es sein das ich zur Zeit kein DataSet in benutzung habe??? Siehe Code

    Also zur zeit gehe ich jedenfalls wie folgt vor...

    VB.NET-Quellcode

    1. '+++ Deklaration beim Start der User Form +++
    2. Dim myconection As New DBConnection
    3. Dim mycmd As New MySqlCommand
    4. Dim dadapter As New MySqlDataAdapter
    5. Dim dtable0 As New DataTable
    6. Dim dtable1 As...
    7. Dim dtable2 As...
    8. Dim dtable3 As...
    9. Dim connect As New MySqlConnection(My.Settings.ConnString)
    10. ' Abrufen der SQL Daten und anzeige in einer DGV
    11. Sub mitarbeiter_in_XML()
    12. Try
    13. mycmd.Connection = myconnection.open 'DB Verbindung öffnen
    14. mycmd.CommandText = "Select * From mitarbeiter Order by Id asc" 'Alle Daten auslesen
    15. dadapter = New MySqlDataAdapter(mycmd)
    16. dtable0.Rows.clear()
    17. dadapter.Fill(dtable0)
    18. myconnection.close()
    19. If Not dtable0 Is Nothing AndAlso dtable0.Rows.Count > 0 Then
    20. 'Befüllt mein DGV
    21. Endif
    22. Catch
    23. End Try
    24. End Sub


    So befülle ich mein DataTable und mit ein paar Zeilen Code mehr befülle ich auch mein GDV

    Ich habe zwar ein DataSet in den Datenquellen, aber was muss ich da noch machen das eine XML Datei mit dem namen "mitarbeiter" beschrieben wird?
    Bin aus den Foren Beiträgen nicht schlauer geworden.

    CodeTags korrigiert ~VaporiZed

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

    Dein Gedanke zwischen der lokalen und der echten DB hin- und herzuwechseln ist aus Datensicht schon recht bedenklich.
    Wie willst Du denn die Datenbestände konstant halten, wenn Du mit mehreren Leuten auf die Zentrale-Datenbank zugreifst. nun Fällt bei 2 Anwendern die Netzwerk- Verbindung aus. Beide arbeiten für 30 min lokal. Nach es gibt jetzt 3 Zustände der Datenbank. Nun müssen die Daten wieder zusammengeführt werden.
    Geh mal davon aus, es ist mindestens ein Datensatz gelöscht wurde, 1 Datensatz befindet sich in 2 und einer in 3 Zuständen und in jeder Version sind noch mehrere Datensätze hinzugekommen.
    Wie bastelst Du dies nun zusammen?
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Naja, man müsste halt für die Techniker den Teil offline vorhalten den sie wirklich brauchen.
    Diese Datensätze müssen gegen Ändern geschützt werden.

    Sollen neue Datensätze unterwegs erzeugt werden, wäre in allem betroffenen Tabellen anstatt Auto increment Unique ID eine GUID zu nutzen.
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.
    Der Fragesteller wird sich schon Gedanken gemacht haben. So wie ich seine Anforderungen verstehe, kommt es einfach nicht vor, dass zwei Leute denselben Datensatz bearbeiten. Da steht EIN Techniker vor EINER Anlage und gibt dazu Wartungsdaten ein.
    Nochmal, guck dir "Dataset only"an und erstelle dir ein Dataset ...
    DatasetOnly: DB-Programmierung ohne Datenbank
    Dataset->Db
    allgemeine Zugriffs-Lösung für: MySql, Access, SqlCe, SqlServer, DatasetOnly
    Danke für die Hilfe

    Ich habe vor ca. 1 1/2 Jahren mit dem Kram angefangen und bin recht schnell von den Data Sets weggekommen ,weil ich mit den Table Adapter Anfragen nicht umgehen konnte. Die habe ich lieber selber mit nem cmd abgesetzt.
    Die Data Sets sind schon echt geil, wenn man mit den eigenarten des Editors umgehen kann, der Knoten ist jedenfalls geplatzt, dank der Videos vom Erfinder des Reads. Ich mag den Editor zwar immer noch nicht, aber anscheinend mag er mich jetzt lieber ;-).

    Danke für die Hilfreichen Gedankenansätze...
    Bin gestern Abend mit der Umstrukturierung fertig geworden, und siehe da es funktioniert alles wunderbar.

    Ich kann meine Remote SQL Datenbank über ein DataSet in meiner Form anzeigen(mit Parent, Child Eigenschaften), ein Backup des ganzen in ein XML File speichern und wenn ich die Datenbank nicht erreichen kann benutzt das Programm das Backup XML File zur Darstellung der Daten.
    Der Techniker hat also bei fehlender Internet Verbindung das XML File (Backup der Datenbank) als Datenquelle oder bei bestehender Internet Verbindung die aktuelle Datenbank. Unsere Techniker müssen nicht zwangsläufig Daten zurück schreiben.
    Das ist vollkommen OK so, da nur die Eckdaten der Anlagen benötigt werden, die er einmal im Jahr wartet.

    Jetzt möchte ich ganz gerne Prüfen ob der Inhalt der XML Datei (diese stellt ja mein Backup der SQL Datenbank dar) ungleich der SQL Datenbank ist.

    Mein Grund Gedanke war folgender:

    Beim Aufruf der User Form wird die Datenbank in das DataSet geschrieben, dieses DataSet speichere ich in einer XML Datei. Dann rufe ich das XML File auf das bei der letzten Programm beendigung erstellt wurde und prüfe ob beide XML Files identisch sind.
    Ist der Gedankenansatz richtig?

    Gibt es in VB einen Befehl wo ich ganz easy über eine Art Compare Funktion File1.xml mit dem Inhalt der File2.xml vergleiche und dann ein True oder False erhalte?

    Codezeile wäre nett ;)

    VB.NET-Quellcode

    1. Public Shared Function CompareFiles(file1 As String, file2 As String) As Boolean
    2. Return System.IO.File.ReadAllText(file1).Equals(System.IO.File.ReadAllText(file2))
    3. End Function


    Ostseebengel74 schrieb:

    Ist der Gedankenansatz richtig?
    Jo, aber vmtl. zu kurz gedacht.
    Es gibt so viele möglichkeiten, warum die Dateien verschieden sein können:
    In der ZentralDB
    • kann ein Datensatz hinzugekommen sein
    • kann ein Datensatz gelöscht worden sein
    • kann ein Datensatz geändert worden sein
    Und in der Peripherie-Datenbank
    • kann ein Datensatz hinzugekommen sein
    • kann ein Datensatz gelöscht worden sein
    • kann ein Datensatz geändert worden sein
    [*]achso - das hatteste ja gesagt, das kommt nicht vor.

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

    Ich würd das Ding in ein zweites DataSet laden und die miteinander vergleichen. Ist bisschen mehr Arbeit, aber dann haste Sicherheit, was unterschiedlich ist.
    Gibt's da nicht auch Merge-Funktionen, mit denen man die Änderungen gleich übernehmen kann?
    Dank der Videos vom "ErfinderDesRades" habe ich das Prinzip der Datases, TableAdapter usw. begriffen. Danke für die tollen Erklärungen und deine Arbeit.

    Es funktioniert soweit auch ganz gut. Der Code ist schlank und die Daten werden korrekt angezeigt und geschrieben.
    Aber...

    ABER:

    Beim erstellen einer neuen Reihe (also einer neuen Id) wird die Id der Tabelle dank "auto einsetzen Mode" immer erhöht. Frei gewordene Id's werden nicht benutzt. Dast Teil zählt nur höher. Das konnte ich früher mit meinen eigenen "Insert to" befehlen umgehen, weil ich vorher nach der nächsten freien ID gesucht habe. Es wurden bei frei gewordenen Id's automatisch die fehlenden ersetzt. Wie kan man das mit den Data sets mach?

    VB.NET-Quellcode

    1. MitarbeiterDataGridView.Sort(MitarbeiterDataGridView.Columns(0), System.ComponentModel.ListSortDirection.Ascending) 'dgv nach id sortieren
    2. Dim reihen As Integer = MitarbeiterDataGridView.Rows.Count 'anzahl der reihen im gdv ermitteln
    3. Dim reihe As Integer = 0
    4. Dim idwert As Integer = 0
    5. Dim idwertdanach As Integer = 0
    6. Dim idfrei As Integer = 0
    7. For reihe = 0 To reihen - 1 'for next schleife die das dgv abruft
    8. idwert = MitarbeiterDataGridView.Rows(reihe).Cells(0).Value ' id dieser reihe speichern
    9. If reihe < reihen - 1 Then
    10. 'msgbox(reihe & " <= " & reihen - 1 & vbcrlf & idwert)
    11. idwertdanach = MitarbeiterDataGridView.Rows(reihe + 1).Cells(0).Value ' id der nächsten reihe speichern
    12. End If
    13. If idwertdanach - 1 > idwert Then
    14. idfrei = idwert + 1
    15. Exit For
    16. End If
    17. Next
    18. If idfrei = 0 Then idfrei = reihen
    19. ' msgbox("gefunden wurde: " & idwert + 1)
    20. ' msgbox("hat einträge: " & reihen & vbcrlf & "gefunden wurde die freie id: " & idfrei & vbcrlf)
    21. MsgBox("es wurde ein mitarbeiter mit der id: " & idfrei & " vorbereitet" & vbCrLf & vbCrLf & "dieser mitarbeiter muss nach dem ausfüllen der gelben eingabefelder gespechert werden.", MsgBoxStyle.Information, "hinweis")
    22. If Online = True Then
    23. MitarbeiterBindingSource.AddNew()
    24. IdUserTextBox.Text = idfrei
    25. MitarbeiterDataGridView.Rows(MitarbeiterDataGridView.Rows.Count - 1).Cells(0).Value = idfrei
    26. End If




    Das oben war jetzt der unelegante versuch die nächste freie Id heraus zu finden.

    Nachdem der Anwender alles eingetippelt hat wird die Codezeile unterhalb aufgerufen.



    VB.NET-Quellcode

    1. MitarbeiterBindingSource.EndEdit()
    2. MitarbeiterBindingSource.ResetItem(MitarbeiterBindingSource.Position)
    3. mitarbeitertableadapter.update(konsoledataset.mitarbeiter)




    Wo liegt mein Denkfehler?

    CodeTags korrigiert ~VaporiZed

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

    Der Denkfehler ist, dass man sowas überhaupt probieren will. Stell Dir vor, dass Du verbundene Tabellen hast, in denen die 28. Zeile von Tabelle2 auf die Tabelle-1-Zeile mit der ID 5 verweist. Wenn Du nun die Tabelle-1-Zeile mit der ID 5 löschst und dann eine neue Zeile hinzufügst, wird die neue Zeile wieder die ID 5 haben. Und wenn's doof läuft, wird die 28. Zeile von Tabelle2 auf diese neue Zeile verweisen, obwohl das gar inhaltlich nicht sinnvoll ist. Beispiel:

    Usertabelle mit
    1. Adam, ID 0, bekannt seit 01.01.2001
    2. Brunhilde, ID 1, bekannt seit 01.01.2003
    3. Christiana, ID 2, bekannt seit 01.01.2005
    Kontozugangsdaten mit
    1. Username BVG99663; Passwort Bar; Username-ID 1
    2. Username Adam1501; Passwort Foo; Username-ID 0
    3. Username GhostInAShellnut; Passwort Baz; Username-ID 2
    Username Brunhilde wird gelöscht und neuer User eingefügt: DoritoTheBest -> bekommt die freigewordene ID 1, bekannt seit 01.01.2022
    Damit hat DoritoTheBest automatisch die Zugangsdaten von Brunhilde, weil Kontozugangsdaten-Zeile 1 ja noch auf die Brunhilde-ID verweist, die nun aber DoritoTheBest gehört.

    Ja, man kann durch richtige Einstellungen im tDS-Designer sowas verhindern (kaskadisiertes Löschen). Aber was könnten dann ggf. Protokolldaten sagen? Dass Brunhilde nie existiert hat, DoritoTheBest aber seit 2003, obwohl dieser User sich erst 2022 angemeldet hat.

    Lass die IDs einfach weiterlaufen. Bei Standardeinstellung hast Du knapp 2 Milliarden Einträge Zeit, bis es Probleme gibt. Wenn Du jeden Tag 1000 neue Einträge erstellst, sind das immer noch knapp 5500 Jahre, bis es da Probleme gibt.

    ##########

    zu Deinem Code: Joa, ich geb Dir recht, kann man als unelegant bezeichnen.
    Müsst ich die nächste freie ID suchen, würd ich alle vergebenen IDs aus der DataTable hernehmen, diese sortieren und dann wohl alle in einer normalen For-Schleife durchgehen. Sobald die ID nicht mit dem Schleifenindex übereinstimmt, hab ich die nächste freie ID.


    Boolean-Vergleiche mit True sind überflüssig.
    Bevor Du weitermachst, bitte die empfohlenen VS-Einstellungen verwenden. Stichwort MsgBox
    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“ ()

    Ostseebengel74 schrieb:

    Beim erstellen einer neuen Reihe (also einer neuen Id) wird die Id der Tabelle dank "auto einsetzen Mode" immer erhöht. Frei gewordene Id's werden nicht benutzt. Dast Teil zählt nur höher. Das konnte ich früher mit meinen eigenen "Insert to" befehlen umgehen, weil ich vorher nach der nächsten freien ID gesucht habe. Es wurden bei frei gewordenen Id's automatisch die fehlenden ersetzt. Wie kan man das mit den Data sets mach?
    Ich wüsste nicht, wie das zuverlässig gehen sollte.
    IDs werden von der DB vergeben - daher kann man sie im Dataset nicht suchen.
    allgemeiner Standard ist auch, dass keine Notwendigkeit gesehen wird, die Reihe der von der DB generierten IDs lückenlos zu gestalten.
    Gut verstanden oder auch nicht
    ...in meiner Tabelle ist die Id ja als Primärschlüssel vergeben. Dieser Primärschlüssel hat vermutlich nichts mit der Identitätsspalte der Tabelle zu tun, Richtig?


    Mit jedem neuen Eintrag wird diese Id erhöht. Ich dachte daher es sei eine Gute Idee diese wieder aufzufüllen, falls zwischen drin mal ein paar gelöscht werden. Rein Theoretisch werden die Id Werte ja im laufe der Jahre sehr groß.

    Also ist das löschen von Einträgen faktisch blöd? Sollte ich stattdessen den Eintrag nicht löschen? Sondern in eine Art Warte Schleife schicken und bei neuanlage eines Mitarbeiters dem die verwaiste Id vergeben?

    Oder lebt man damit das die Werte der Id's in das unendliche steigen?

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

    Ostseebengel74 schrieb:

    Also ist das löschen von Einträgen faktisch blöd?
    Eigentlich schon.
    Statt dessen würde ich den User auf inaktiv setzen.
    Sonst läufst du Gefahr, dass alle dem User zugeordnete Datensätze in der Luft hängen.
    Oder, noch schlimmer, du legst einen neuen User mit dieser ID an und erbst damit alle referenzierten Datensätze des alten User.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Ostseebengel74 schrieb:

    Oder lebt man damit das die Werte der Id's in das unendliche steigen?
    So ist es.
    Daher sind Ids ja vom Datentyp Integer - Maximalwert ist 2^31 - das ist schon ziemlich viel.

    Übrigens laufen die IDs im typDataset angelegter Neu-Datensätze ins Negative, und das ist auch sinnvoll - damit das klar getrennt ist.
    Weil beim Update schickt die DB die neue (positive) Id zurück, und die wird ja im Dataset eingetragen.
    Das gäbe Kuddelmuddel, wenn die DB eine Id returnte, dies im Dataset schon gibt.



    löschen von Einträgen
    Eine Db-Infrastruktur muss natürlich auch Löschvorgänge unterstützen.
    Es kommt numal vor, dass man was falsches eingibt, und wieder entfernen möchte.
    Wenn Datensätze nach Löschungen in der Luft hängen, dann ist die DB falsch designet.
    Tatsächlich stellt man referentielle Integrität ein, und dann kann die DB einen Parent-Datensatz garnet löschen, wenn da noch Children anhängig sind.
    Zusätzlich kann man auch Löschweitergabe konfigurieren, dann haut die DB selbst die Children weg (ist in vielen Fällen sehr praktisch, aber zB mit User-Daten vlt. doch bisserl sehr heikel).

    Ansonsten in Praxis grosser Datenbanken löscht man sehr selten - meist wird wie gesagt mit Aktiv-Flags gearbeitet.

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

    Ok jetzt habe ich verstanden...

    Frage am Rande

    ich benutze PHPmyAdmin für die Datenbank... kann man da leere Tabellen Rows einsehen? Mir werden dort ja nur die vorhandenen Einträge angezeigt.

    Zum Glück habe ich noch nicht zu viele Einträge, kann man handisch gelöschte rows aus der Struktur nehmen?
    ich hab vor langem mal PHPmyAdmin angemacht, und fand es ganz grauenhaft.
    Ich hab z.B. nicht gefunden, wie man damit überhaupt eine Relation mit referentieller Integrität einrichtet, oder gar mit Löschweitergabe.

    Da hab ich jetzt Sorge, dass diese essentiellen Dinge deiner DB völlig abgehen.
    Wenn dem so ist braucht man mit DbPersistance etc nicht weitermachen, sondern muss erst die DB in Ordnung bringen.
    Kannst du einen Screenshot deines ER-Diagramms einstellen?

    Wenn deine Connectoren funktionieren, dann geht auch ein Bild des generierten typisierten Datasets - das ist ja auch ein ER-Diagramm.



    Ansonsten: Was ist eine "leere Tabellen-Row"?
    Bzw. natürlich kann man die einsehen, aber deren Einträge werden halt leer sein.
    Und natürlich werden dir nur vorhandene Einträge angezeigt - nicht vorhandene Einträge wird kein Tool der Welt dir anzeigen können.