PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C#/.NET] Datenbank/GUI: Wie synchronisieren?


Expandable
2007-11-22, 11:45:24
Hallo allerseits,

ich überlege mir seit ein paar Tagen die wohl beste Implementierung für folgendes Problem, und würde mal gerne wissen, was ihr davon haltet, bzw., wenn ihr mit sowas schon Erfahrung habt, was die beste Vorgehensweise ist.

Folgende Situation: Ich habe eine Datenbank auf meinem Rechner (SQL Server Express) sowie eine C#-GUI Anwendung. Die GUI soll mir verschiedene Daten aus der DB anzeigen, und auch neue Daten einfügen können. Also ziemlicher Standard.

Das Problem ist nun, dass eine andere (nicht von mir geschriebene) Anwendung Daten in die DB einfügt. Diese neue Daten sollen in meiner GUI mehr oder weniger sofort angezeigt werden. Dazu habe ich einen Trigger in der Datenbank, der mir in einer Tabelle aufzeigt, welche Zeilen in welcher Tabelle verändert wurden (insert/delete/update). Meine GUI-Anwendung fragt nun alle paar Sekunden diese Tabelle ab und soll die Änderungen in der GUI anzeigen.

Problembereich 1) Ist es sinnvoll, ständig die DB zu befragen, wenn ein Formular geöffnet wird? Wenn also z.B. in einer Form in einer ComboBox eine Liste von sagen wir Usern angezeigt werden soll, soll dann bei jedem Öffnen der Form die User-Liste aus der DB geholt werden, oder sollte das gecacht werden? Sinnvoll, weil dann immer der aktuelle Stand der DB in der Liste angezeigt wird. Beim Cachen haben wir die gleichen Synchronisierungsprobleme wie bei (2). Problematisch, weil ein Zugriff auf die DB u.U. etwas länger dauern kann, oder sonstige Fehler/Probleme beim DB-Zugriff auftauchen könnten. Jedes Formular muss also mit DB-Fehlern umgehen können.

Problembereich 2) Der Stand der DB zum Startpunkt der GUI-Anwendung wird gecacht. Das Programm zeigt (vereinfacht gesagt) eine Liste aller Einträge in einer Tabelle an. Ein "Writer-Thread" pollt nun die DB nach Änderungen, wenn er welche findet, werden die gecachten Objekte aktualisiert. Nun muss die Änderung an die GUI übergeben werden. Problem: Thread-Synchronisierung. Habe ich eine Liste, sagen wir List<User>, und diese ist die DataSource z.B. einer ComboBox, darf darauf nur aus dem GUI-Thread zugegriffen werden. D.h., mein Writer-Thread muss zum Updaten der Liste in den GUI-Thread wechseln. Das ginge ja per Control.Invoke irgendwie. Falls das Update aber länger dauert, wird damit meine GUI blockiert. Lösung: Eine Kopie der Liste und aller Objekte an die GUI binden. Da ist aber der Nachteil, dass alle Objekte doppelt oder mehrfach vorhanden sind. Allerdings kann man den Zeitpunkt der GUI-Updates (und ob Teile der GUI überhaupt unbedingt aktualisiert werden müssen), besser bestimmen. Allerdings haben wir dann ggf. mehrere Listen, die eigentlich das gleiche sein sollten im Programm, die teilweise komplett unterschiedliche Daten enthalten können.

Ich hoffe, mein Problem ist einigermaßen klar geworden. Falls nicht, bitte noch einmal nachfragen. Ich würde nun gerne wissen, wie man so etwas am besten löst? Habt ihr Erfahrungen damit oder irgendwelche Hinweise zu OpenSource-Programmen, die soetwas lösen bzw. irgendwelche Blogs/Artikel zu diesem Thema?

Vielen Dank!

ethrandil
2007-11-22, 22:48:06
Aalso es ist im Prinzip schon okay, wenn jedes Mal wenn das Formular angezeigt wird, die Datenbank gefragt wird. GUI-Code ist eh lahm, da macht das auch nix mehr aus.
So rein theoretisch müsstest du dann aber den Datenbankeintrag solange locken, wie das GUI auf ist! Weil sonst kann es ja zu unbeabsichtigten Änderungen kommen, wenn die Datenbank während das GUI angezeigt wird, verändert wird.
Ich weiß ja nicht, was deine Anwendung ist und welche DB du verwendest ;)

-eth

Bietchiebatchie
2007-11-23, 17:17:10
Problembereich 1) Ist es sinnvoll, ständig die DB zu befragen, wenn ein Formular geöffnet wird? Wenn also z.B. in einer Form in einer ComboBox eine Liste von sagen wir Usern angezeigt werden soll, soll dann bei jedem Öffnen der Form die User-Liste aus der DB geholt werden, oder sollte das gecacht werden? Sinnvoll, weil dann immer der aktuelle Stand der DB in der Liste angezeigt wird. Beim Cachen haben wir die gleichen Synchronisierungsprobleme wie bei (2). Problematisch, weil ein Zugriff auf die DB u.U. etwas länger dauern kann, oder sonstige Fehler/Probleme beim DB-Zugriff auftauchen könnten. Jedes Formular muss also mit DB-Fehlern umgehen können.
Selbst wenn dein DB-Server in Australien steht und zehn User parallel die ganze Sache nutzen sollen: Solange das nicht 100.000 Zeilen sind - wovon ich einfach mal ausgehe, denn es was willst du mit einer Tabelle mit 100.000 Einträgen anfangen? - gibt es keinen Grund da irgendwas zu cachen.


Problembereich 2) Der Stand der DB zum Startpunkt der GUI-Anwendung wird gecacht. Das Programm zeigt (vereinfacht gesagt) eine Liste aller Einträge in einer Tabelle an. Ein "Writer-Thread" pollt nun die DB nach Änderungen, wenn er welche findet, werden die gecachten Objekte aktualisiert. Nun muss die Änderung an die GUI übergeben werden. Problem: Thread-Synchronisierung. Habe ich eine Liste, sagen wir List<User>, und diese ist die DataSource z.B. einer ComboBox, darf darauf nur aus dem GUI-Thread zugegriffen werden. D.h., mein Writer-Thread muss zum Updaten der Liste in den GUI-Thread wechseln. Das ginge ja per Control.Invoke irgendwie. Falls das Update aber länger dauert, wird damit meine GUI blockiert.
Wieso braucht das update zeit?
Wenn du sowas in dem "Writer-Thread" machst:
List<User> newUser = DAL.GetNewUsers();
comboxBox.Invoke( .. comboxBox.DataSource = newUsers; }
dann sehe ich nix, was im GUI-Thread Zeit benötigen sollte.

Wenn ich ehrlich sein soll: Ich sehe da eigentlich kein Problem, außer du willst dir das Leben irgendwie schwer machen mit dem Cachen...

Schreib mal kurz:
a) von welchen Größenordnung wir hier reden (DB-Größe, User, Daten pro Zeile etc.)
b) inwiefern die Einträge in der DB von der Form-Anwendung geändert werden können.
c) was soll passieren, wenn zwei User den selben Datensatz bearbeiten oder soll dies von vornerein ausgeschlossen sein?