Laden...

Client/Server Anwendung - Datenänderungen den Clients mitteilem

Erstellt von Christoph Burgdorf vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.458 Views
Christoph Burgdorf Themenstarter:in
365 Beiträge seit 2004
vor 14 Jahren
Client/Server Anwendung - Datenänderungen den Clients mitteilem

Hallo Community!

Ich plane derzeit ein Programm zur Optimierung des Produktionsprozesses in einem Fertigungsbetrieb. Ziel ist es, dass Produktionsaufträge von mehreren Clients erfasst und von anderen Clients ausgelesen werden können. Die Clients, die die Aufträge auslesen arbeiten prinzipiell wie die Tafeln am Flughafen Terminal. Man sieht neue Aufträge eintrudeln, alte fliegen raus etc. pp.

Das ganze soll als Client/Server Anwendung realisiert werden. Obwohl ich gerne das Entity Framework ausprobieren würde, habe ich mir gedacht, dass ich die Produktionsaufträge doch besser einfach in einer DataTable halte. Durch den fehlenden RowState der Objekte im EntityFramework, scheint mir dies die bessere Wahl.

Siehe hierzu: Entity Framework auf Änderungen überprüfen (Antwort von Rainbird)

Oder auch: http://yellow-rainbird.de/blogs/rainbird/archive/2009/01/09/habe-sehnsucht-nach-dem-rowstate.aspx

Ich hangel mich bei der Entwicklung an Rainbirds Appserver samt Beispiel lang (Rainbirds Appserver). Das bedeutet nicht, dass ich den Appserver benutze, sondern vielmehr versuche ihn als Orientierung zu benutzen. Ich erhoffe mir auf diese Weise einen höheren Lerneffekt. Rainbird, an dieser Stelle noch mal vielen Dank für die Veröffentlichung deiner Arbeit.

Ich habe ebenfalls vor den Code zu veröffentlichen, wenngleich das auch nicht so spannend wie der Applikationsserver sein wird. Vielleicht ist es aber dafür für absolute Anfänger umso interessanter.

Vorab habe ich allerdings bereits einige offene Fragen 😃

Mitteilung geänderter und gelöschter Datensätze an alle Clients

Wie genau macht man das richtig? Fakt ist, dass die Clients binnen Sekunden über gelöschte und geänderte Datensätze informiert werden sollen.

Ich hatte ursprünlich vor auf dem Server eine DataTable mit allen Produktionsaufträgen zu halten und alle Update, Delete und Insert Operationen direkt auf dieser DataTable vorzunehmen. Alle Clients könnten sich dann alle X Sekunden wieder diese DataTable ziehen. Auf diese Weise verschwindet ein gelöschter Datensatz auch umgehend auf allen Terminals.

Allerdings erscheint mir diese Lösung wenig elegant und nicht besonders ressourcenschonend.

Wie sähe aber die Alternative aus? Ich kann bei jeder Änderung einen TimeStamp updaten und dann nur die geänderten Datensätze auf die Clients übertragen. Wie allerdings läuft das bei den gelöschten Datensätzen? Protokolliert man auf dem Server alle gelöschten Datensätze mit, sodass die Clients diese abfragen und aus ihren lokalen DataTables entfernen können?

One Way Kommunikation - Generelles Verständnis

Nur noch mal zum generellen Verständnis. Wenn ich mir vom Server eine DataTable Instanz zurückgeben lasse und hier jetzt etwas verändere, dann werden die Daten nicht automatisch auf die Instanz auf dem Server übertragen, richtig? Das liegt so in der Natur der One Way Kommunikation? Stattdessen stelle ich in meiner Service Klasse Methoden bereit, denen ich die Änderungen übergebe und die vom Client aus intiiert werden können. Richtig?

Gruß

Christoph

3.728 Beiträge seit 2005
vor 14 Jahren
Benachrichtigung

Hallo bvsn,

der zentrale Dienst auf dem Server kann die Clients per Callback (das funktioniert sowohl mit Remoting, als auch mit WCF) benachrichtigen, wenn sich am Status eines Produktionsauftrags etwas ändert, oder wenn ein neuer Auftrag eingebucht wurde. Die Clients müssen dazu eine Methode bereitstellen, die der Server aufrufen kann, um über Änderungen zu benachrichtigen. Jeder Client registriert sich beim Produktionsauftrags-Dienst und übergibt einen Verweis auf die Rückrufmethode an den Server, damit dieser über Änderungen benachrichtigen kann.

Ich würde die geänderten Daten bei der Benachrichtigung nicht unbedingt gleich übertragen. Wenn ein Client eine bestimmte Benachrichtigung über eine Statusänderung interessiert, kann er sich selber die neue Auftragsliste oder auch die Delta-Daten davon vom Server besorgen. Die Benachrichtigungen bleiben so kurz und knackig. So wird sichergestellt, dass sie möglichst alle Clients fast gleichzeitig erreichen. Der Server muss quasi nur sagen "Es hat sich was geändert". Je nach Komplexität des Systems kann es noch sinnvoll sein, ein paar Infos mitzugeben, was genau passiert ist (z.B. 1 x neu, 2 x geändert, 1 x gelöscht).

Transaktionen nicht vergessen (wegen der Threadsicherheit)!

Das Entity Framework soll mit .NET 4.0 besser n-Tier-Unterstützung bekommen: http://blogs.msdn.com/adonet/archive/2009/05/14/sneak-preview-n-tier-development-with-entity-framework-4-0.aspx
Natürlich ist das noch Zukunftsmusik und nützt in den aktuellen Projekten noch gar nix, aber es ist trotzdem gut zu wissen.

Christoph Burgdorf Themenstarter:in
365 Beiträge seit 2004
vor 14 Jahren

Hi Rainbird,

danke für deine Antwort. Ok, das macht Sinn. Ich versuche das so umzusetzen.

Gruß

Christoph

Christoph Burgdorf Themenstarter:in
365 Beiträge seit 2004
vor 14 Jahren

Ich habe bezüglich der Deltadaten noch mal eine Frage. Die neuen und geänderten Daten abzufragen ist ja prinzipiell kein Problem, da man in den Datensätzen Created und Changed TimeStamps speichern kann. Aber die gelöschten Datensätze müssen irgendwo separat gespeichert werden.

Wenn dann also ein Client die Deltainformationen abrufen möchte, ruft er alle neuen und geänderten Datensätze seit dem letzten Check ab. Und löscht zusätzlich alle Datensätze deren IDs in der Löschliste nach dem letzten Check eingetragen wurden.

Nur frage ich mich jetzt: Wo genau wird diese Löschliste gespeichert? Führe ich einfach auf dem Server eine Liste mit, die ich nicht persistiere? Dann wäre allerdings die nächste Frage: Wie groß darf diese Liste werden (Stichwort: Statusloser Server). Oder anders, wie wird sie bereinigt. Der Server weiß ja prinzipiell nicht welcher Client die Löschinformationen bis zu welchem Zeitpunkt abgerufen hat. Oder speichere ich diese Änderungsliste besser in der Datenbank?

Gruß

Christoph

3.728 Beiträge seit 2005
vor 14 Jahren
Deltadaten

Um wie viele Datensätze handelt es sich denn überhaupt? Wenn es nicht tausende von Datensätzen sind, würde ich immer alles komplett abrufen. Eine Inkrementelle Synchronisierung ist wesentlich aufwändiger zu entwickeln und auch viel fehleranfälliger. Du solltest überlegen, ob dieser große Aufwand am Ende einen betriebswirtschaftlich verargumentierbaren Mehrwert bringt (Ich vermute nicht).

Ich wollte eigentlich nur verschiedene Möglichkeiten aufzeigen, was man machen kann.

Das mit der Löschliste versteh ich aber nicht. Der Server versucht nicht zu wissen, welchen Datenbestand jeder einzelne Client gerade hat, um die passenden Delta-Daten liefern zu können. Die Synchronisierung würde immer vom Client aus gehen. Ein Client sendet dazu eine Liste der IDs + Zeitstempel, die er momentan geladen hat und entsprechende Filterkriterien. Der Server prüft die Liste gegen den aktuellen Datenbestand und erzeugt eine Liste mit den Deltadaten. In dieser Delta-Liste hat jeder Eintrag einen Enum-Wert, welcher die Änderung beschreibt (New,Geändert, Gelöscht) und enthält natürlich die aktuellen Daten. Datensätze, die sich nicht verändert haben, tauchen auf der Delta-Liste nicht auf. Der Client kann, sobald der die Delta-Liste vom Server zurückbekommen hat, diese mit seinem lokalen Datenbestand synchronisieren.

Wozu also irgendwelche getrennten Löschlisten pflegen?

Aber wie gesagt, lohnt sich der Aufwand für so eine Delta-Verarbeitung nur, wenn es sehr viele Datensätze sind, die bei einem Komplettabruf vom Server geladen werden müssten.

E
107 Beiträge seit 2008
vor 14 Jahren

Guten Morgen,

ich mische mich nur ungerne ein, gerade wenn Rainbird schon beteiligt ist ( da lerne ich beim mitlesen immer dazu 😃 ).

Aber ich habe mich vor kurzem mit einem ähnlichen Thema beschäftigt habe, sprich mehrere Clients und eine solche Statusliste mit Aufträgen, welche auf den Clients immer aktuell gehalten werden soll. Letztendlich habe ich mich dann für den ServiceBroker-Dienst des SQL-Server 2005 (auch in der Express-Edition verfügbar) entschieden, die Funktionsweise hat Rainbird ja schon beschrieben:

der zentrale Dienst auf dem Server kann die Clients per Callback (das funktioniert sowohl mit Remoting, als auch mit WCF) benachrichtigen, wenn sich am Status eines Produktionsauftrags etwas ändert, oder wenn ein neuer Auftrag eingebucht wurde. Die Clients müssen dazu eine Methode bereitstellen, die der Server aufrufen kann, um über Änderungen zu benachrichtigen. Jeder Client registriert sich beim Produktionsauftrags-Dienst und übergibt einen Verweis auf die Rückrufmethode an den Server, damit dieser über Änderungen benachrichtigen kann.

Dabei wird ja nur meine Tabelle 'Aufträge' der Datenbank auf Änderungen überwacht, etc.
Dazu kann ich nur sagen, dass es (bisher) super funktioniert, allerdings spreche ich hier von einer DataTable mit meisstens ~ 40 Einträgen. Natürlich mal etwas mehr und etwas weniger. Gelöschte Datensätze schreibe ich via Trigger in eine extra Tabelle der Datenbank. Die Problematik der beschriebenen "Löschliste" kann ich also nicht ganz nachvollziehen. Ressourcentechnisch (ca. 35 Clients) gibt es da bisher ebenfalls keine Probleme, allerdings wird auch nicht durchgehend an allen Clients gearbeitet, sondern ~immer alle 2-3 Minuten sind "ein paar" aktiv. Ob das für dich in Frage kommt, musst du selbst entscheiden. Wollte das nur mal kurz beschreiben, um a) evtl. noch etwas dazu zu lernen (aber nicht in diesem thread) und natürlich b) dir bei interesse mehr infos zur umsetzung zu geben.

Ich muss dazu sagen, dass ich noch keinen anderen Weg gegangen bin und mich interessehalber auch mal mit dem "Deltadaten"-Ansatz auseinander setzen möchte.

Gruß

Ich lasse mich gerne korrigieren! (:

J
1.114 Beiträge seit 2007
vor 14 Jahren

Würds auch so machen wie Rainbird, mit einem Remoting oder WCF Server.

Der Server muss natürlich auch noch irgendwie mitkriegen, wann sich die Daten in der DB ändern, damit er weiss, wann die clients benachrichtigt werden sollen.

Interessant in dem Zusammenhang dürft der SqlDependency Thread sein. Da wird am Server ein Event ausgelöst, sobald sich die zugrunde liegende Datenmeng in der DB ändert. Das erspart dir lästiges Pollen.

Christoph Burgdorf Themenstarter:in
365 Beiträge seit 2004
vor 14 Jahren

@Rainbird

das mit der Löschliste war vielleicht etwas umständlich gedacht. Ich bin nicht davon ausgegangen, dass der Client sich mit einer Liste seiner geladenen IDs an den Server wendet. Deswegen war mein Ansatz, dass ich mitprotokolliere was gelöscht wird, damit der Client nachsieht, ob seit dem letzten Check etwas gelöscht wurde.

Du hast aber vermutlich recht, dass es mehr Sinn macht die Daten komplett zu ziehen. Es handelt sich in der Regel wohl um nicht mehr als 20 - 50 schlanke Datensätze. Ich hatte irgendwie gedacht es wäre bad practise alles zu ziehen, wenn sich ggf. nur einzelne Datensätze geändert haben.

@eveN @Jelly

Die Server Events sind zwar sehr interessant. Ich möchte die Lösung aber möglichst Datenbankneutral halten.