Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Servergeänderte Datensätze (https://www.delphipraxis.net/187170-servergeaenderte-datensaetze.html)

Sugar 3. Nov 2015 16:53

Servergeänderte Datensätze
 
Hallo Forum,

ich habe eine kleine Anwendung geschrieben um das unsägliche rumgefummel in einer Excel-Tabelle von 12 Mitarbeitern zu beenden.Eine Schwäche des Programms ist, der Client bekommt nicht mit, wenn ein anderer Client einen Datensatz ändert. Ich überlege nun ratlos wie ich sowas umsetzen könnte.

Zum Anwendungsfall: Es ist im Prinzip ein kleine wenig aufgeblasener Kalender bei dem im Vorfeld sämtliche notwendigen Datensätze "leer" angelegt werden und dann vom Anwender ausgefüllt werden. Deswegen müsste ich auf das Ändern von DS reagieren.

Hat jemand sowas schonmal umgesetzt oder hat Tipps dazu wie man sowas erreichen kann? Von der Kontruktion her könnte ich in den Userverzeichnissen eine Datei ablegen auf die dann alle angemeldeten Clients reagieren und die Tabellen aupdaten. Aber das geht doch sicher etwas eleganter, oder?

Ich nutze D7 und SQL-Server 2012

Danke für Tipps
Heiko

haentschman 3. Nov 2015 17:13

AW: Servergeänderte Datensätze
 
Hallo...

Fragen:
* Wie greifst du auf den Server zu? ADO?

Tipps:
* bei einem modernen DBMS nie mit Tabellen arbeiten sondern nur über Query welche sich nur die Daten holt die benötigt werden. (SQL)
* vernünftige Datenzugriffskomponenten (Devart, FireDAC)... mit D7 etwas schwierig
* Trennung der Datenbankschicht von der Oberfläche... keine datensensitiven Controls. (war vor Jahren State of Art)
* MSSQL Server Events https://msdn.microsoft.com/en-us/library/ms189453.aspx

...da hast du Brot. :thumb:

Sugar 3. Nov 2015 17:33

AW: Servergeänderte Datensätze
 
Zitat:

Zitat von haentschman (Beitrag 1320442)
Hallo...

Fragen:
* Wie greifst du auf den Server zu? ADO?

Tipps:
* bei einem modernen DBMS nie mit Tabellen arbeiten sondern nur über Query welche sich nur die Daten holt die benötigt werden. (SQL)
* vernünftige Datenzugriffskomponenten (Devart, FireDAC)... mit D7 etwas schwierig
* Trennung der Datenbankschicht von der Oberfläche... keine datensensitiven Controls. (war vor Jahren State of Art)
* MSSQL Server Events https://msdn.microsoft.com/en-us/library/ms189453.aspx

...da hast du Brot. :thumb:

Ja, ich greife über ADO auf den SQL Server zu.

Zu deinen Tipps:

Ich muss leider - exakt aus Gründen der Performance - mit ein paar Tabellen arbeiten. Alle sinnvollen Daten hole ich mir natürlich mit AdoQueries. Und, man mag es veraltet halten, aber ohne datensensitive Controls stände ich jetzt vor dem gleichen Problem.

Dein Link, danke dafür, hilft mir nach erster Analyse auch nicht weiter. So wie ich es verstehe, müsste der Client nur woanders nach einer Änderung suchen. Ich "überwache" nur eine andere Tabelle.

Perlsau 3. Nov 2015 19:06

AW: Servergeänderte Datensätze
 
Man kann in diversen Datenbanken, u.a. in MsSQL und in Firebird, sogenannte Ereignisse deklarieren (Trigger kennst du ja vermutlich schon). Diese Ereignisse werden dann an alle Clients versandt, die entsprechend darauf reagieren können. Ob deine uralte Delphiversion bereits entsprechende Komponenten bereitstellt, weiß ich natürlich nicht. Notfalls kannst du aber auch mit Zeos arbeiten, dort gibt's zwei sog. EventAlerter-Komponenten. Wenn nun ein Client einen Datensatz ändert und die anderen Clients diesen Alert erhalten, reagieren letztgenannte einfach mit einen Refresh. Wie das bei igendwelchen Konfliktfällen (z.B. Client A hat Datensatz 547 gerade gelöscht, während Client B diesen noch in Bearbeitung hat) genau aussieht, vermag ich jetzt nicht im Detail zu erklären.

p80286 3. Nov 2015 22:01

AW: Servergeänderte Datensätze
 
Zitat:

Zitat von Sugar (Beitrag 1320443)

Ja, ich greife über ADO auf den SQL Server zu.

Zu deinen Tipps:

Ich muss leider - exakt aus Gründen der Performance - mit ein paar Tabellen arbeiten. Alle sinnvollen Daten hole ich mir natürlich mit AdoQueries. Und, man mag es veraltet halten, aber ohne datensensitive Controls stände ich jetzt vor dem gleichen Problem.

Was eine Mehrzahl von Tabellen mit Performance zu tun hat ist mir schleierhaft.

Zitat:

Zitat von Sugar (Beitrag 1320443)
Dein Link, danke dafür, hilft mir nach erster Analyse auch nicht weiter. So wie ich es verstehe, müsste der Client nur woanders nach einer Änderung suchen. Ich "überwache" nur eine andere Tabelle.

Nein, er wird benachrichtigt!

Gruß
K-H

hoika 4. Nov 2015 06:47

AW: Servergeänderte Datensätze
 
Hallo,
er benutzt TAdoTable, weil es sich so besser mit seinen datensensitiven Elementen (TDBEdit usw.) arbeiten läßt.
Kennt TAdoQuery eigentlich auch das RequestLive ?
Damit klappte war ein TQuery doch fast so gut wir ein TTable.
Hatte ich aber nie benutzt.


Heiko

Dejan Vu 4. Nov 2015 07:11

AW: Servergeänderte Datensätze
 
Die Problematik schreit eigentlich nach einem Service (aka Mittelschicht). Zugriff auf die Daten über den Service, der dann ja alle Clients benachrichtigen kann.

ADO unterstützt keine Event notifications. Man müsste also den Provider wechseln (AnyDac) oder sich eben den Service selbst schreiben. Fragt sich, was billiger ist ;-)

FBrust 4. Nov 2015 07:25

AW: Servergeänderte Datensätze
 
Hallo,

als kleinere Zwischenlösung könntest Du auch folgendes machen:

- In jeder Tabelle gibt es ein Feld mit Datum/Zeit der letzten Änderung
- Wenn ein Datensatz bearbeitet wird, wird das Feld im Client zwischengespeichert
- Bevor ein Datensatz dann gespeichert werden soll, wird das Datum der letzten Änderung nochmal
aus der Datenbank gelesen und mit dem zwischengespeicherten verglichen
- Ist das Datum unterschiedlich, wurde der Datensatz in der Zwischenzeit geändert

oder Du setzt beim "Holen" eines Datensatzes ein Feld in der Tabelle, das allen
anderen signalisiert, dass der Datensatz gesperrt ist (dann kannst Du auch hinterlegen, von wem und seit wann)

Aber ein Service ist langfristig natürlich die bessere Wahl.

Gruß
Frank

TheMiller 4. Nov 2015 08:40

AW: Servergeänderte Datensätze
 
Du könntest auch sog. MessageQueues benutzen. Die Windows-Server haben die MS-MessageQueue mit an Board, welche man über die Serververwaltung nachinstallieren kann. Jedes Windows-OS ab 7 aufwärts (glaube ich), hat dieses Feature als Server auch integriert (bzw. ist nachinstallierbar).

Ansonsten kannst du auch RabbitMQ / ApacheMQ verwenden, wenn du eine Linux-VM erstellen kannst.

Dann kannst du bei jeder Änderung eine Nachricht an die MessageQueue schicken, welche alle aktiven Clients benachrichtigt.

Alternativ kannst du auch - wenn es nur um die Meldung geänderter Datensätze aus einem Modul geht - einen TCP-Server u Client verwenden und nach dem Ändern eines DS eine Broadcast-Message (oder alle aktiven Clients) via TCP/IP ansprechen und den String "/reload-1234" senden. Beim Empfangen wissen die TCP-Clients, dass die den DS 1234 aktualisieren müssen.

Sugar 4. Nov 2015 08:49

AW: Servergeänderte Datensätze
 
Vielen Dank an alle. Also, die Anwendung ist mir für eine Investition in andere Zugriffskomponenten einfach zu minimal.

Ich würde mir aber gerne mal die Lösung mit dem Service, wenigstens in der Theorie, ansehen. Kennt einer hilfreiche Links oder andere Quellen (democode) dazu?

Sir Rufo 4. Nov 2015 16:22

AW: Servergeänderte Datensätze
 
Der MS-SQL-Server kennt den Feldtyp RowVersion von daher braucht man sich dort nicht mit einem Timestamp herumärgern.

mm1256 4. Nov 2015 18:06

AW: Servergeänderte Datensätze
 
Zitat:

Zitat von Sugar (Beitrag 1320481)
Vielen Dank an alle. Also, die Anwendung ist mir für eine Investition in andere Zugriffskomponenten einfach zu minimal.

Ich würde mir aber gerne mal die Lösung mit dem Service, wenigstens in der Theorie, ansehen. Kennt einer hilfreiche Links oder andere Quellen (democode) dazu?

Den Service selber zu programmieren würde ich nicht machen. Der Aufwand ist viel zu hoch. Folglich müsstest du hier auch wieder auf Komponenten von Drittanbietern zurückgreifen, z.B. das Trio Aurelius/Sparkle/XData von TMS.

Auch wenn es aus technischer Sicht nicht vom Feinsten und State of the Art ist, würde ich in diesem speziellen Fall (soweit ich dies anhand der verfügbaren Informationen beurteilen kann) mit einer Variante der bereits vorgeschlagenen Lock-Mechanismen arbeiten. Entweder eine separate Lock-Tabelle, oder entsprechende Lock-Felder bei den Datensätzen. Das einzig knifflige Problem dabei ist, wie man mit Verbindungsabbrüchen umgeht. Ein Client lockt, und verabschiedet sich. Wer hebt den Lockmechanismus dann wieder auf? Ist also auch nicht das gelbe vom Ei.

Wie wäre es denn mit einem Mechanismus, wie ihn die uralte B-Tree-Shell von EDV-Beratung Enz schon zu DOS-Zeiten verwendet hat. Ich verwende ihn teilweise heute noch. Es ist quasi eine "lokal auf dem Client arbeitende Mittelschicht".

Es werden insgesamt 3 Datenpuffer verwendet:

- Bei Beginn des Editiervorganges wird der Inhalt des aktuellen Datensatzes in Puffer 1 gelesen
- Puffer 1 wird in Puffer 2 kopiert, das ist der Editierpuffer mit dem der User arbeitet
- Nach dem Editieren und vor dem Post wird Puffer 2 mit Puffer 1 verglichen. Besteht kein Unterschied (der User hat nichts geändert) muss in der DB nicht gepostet werden. Man spart sich also den Post. Andernfalls wird Puffer 3 vom aktuellen Datensatz aus der DB gelesen und mit Puffer 2 verglichen
- Ist der Vergleich positiv (beide Puffer sind gleich) hat womöglich ein anderer User bereits die selben Änderungen vorgenommen. Man spart sich also wieder den Post. Bei negativem Vergleich kann man dem User dann wahlweise

a) die geänderten Daten aus Puffer 3 nochmals zum Editieren anbieten
b) seine eigenen Änderungen verwerfen
c) beide Varianten anzeigen und einen Mix daraus bilden. Das muss im Einzelfall entschieden werden.

Dieses Prinzip hatte für den Arbeitgeber den Vorteil, dass sich die Mitarbeiter nie lange mit dem Editieren aufgehalten haben. Es könnte ja sein, dass ein Anderer "gewinnt". So nebenbei hat man auch ein UnDo während des Editierens.

Für die Erstellung der Puffer braucht man lediglich eine einzige Funktion, dazu dann noch die Vergleichsfunktion, was den Zeitaufwand sehr in Grenzen hält.

Perlsau 4. Nov 2015 20:12

AW: Servergeänderte Datensätze
 
Wieso ist der Vorschlag, die entsprechende – kostenlose – Event-Komponente von Zeos zu verwenden, inakzeptabel oder nicht diskussionswürdig?

Dejan Vu 5. Nov 2015 07:14

AW: Servergeänderte Datensätze
 
Zitat:

Zitat von Sir Rufo (Beitrag 1320569)
Der MS-SQL-Server kennt den Feldtyp RowVersion von daher braucht man sich dort nicht mit einem Timestamp herumärgern.

Ich dachte auch immer, das der T-SQL Datentyp 'TimeStamp' irgendwas mit der Zeit zu tun hat. Aber in Wirklichkeit ist 'TimeStamp' nur die veraltete Version der RowVersion.

@Perlsau: Vermutlich, weil es nichts zu diskutieren gibt. Funzt. Fertig. Noch Fragen? :mrgreen:

Hansa 5. Nov 2015 10:12

AW: Servergeänderte Datensätze
 
Zitat:

Zitat von mm1256 (Beitrag 1320576)
Wie wäre es denn mit einem Mechanismus, wie ihn die uralte B-Tree-Shell von EDV-Beratung Enz schon zu DOS-Zeiten verwendet hat.

Uff, das kennt hier noch jemand ? :shock: Ja, die Basis war die Btree-Isam vom Dipl.-Mathematiker Ralph Nagel. Die angesprochene Zwischenschicht war dann die Btree-Shell. Die kam aber erst dank OOP. War schon cool. Leider ging die Fa. Enz wegen Delphi 1 pleite. Warum ? Wohl weil ein Haupt-Umsatzträger Object Professional (TurboPower) war. Da gab es z.B. brauchbare Editfelder usw. So etwas war dann aber bei Delphi dann auch von Anfang an dabei. Ich kenne Enz und Nagel. Die gingen beide zu KHK (heute Sage). Es gab ja auch deutsche (gedruckte) Handbücher. Übersetzung, Drucken usw. das war wohl auch letztenendes zu teuer. Schade.

Aber zum Thema : Grundlage waren prinzipiell 3 Datensatzversionen. Genannt Savebuffer, Workbuffer und Tempbuffer. Beim Lesen eines Datensatzes werden Savebuffer und Workbuffer mit dem gelesenen Datensatz gefüllt. Savebuffer dient dabei zum späteren Vergleich auf zwischenzeitlich von anderem User durchgeführte Änderungen. Workbuffer ist das, was gerade z.B. editiert wird.

Beim Abspeichern (wäre dann das im Workbuffer) hat die Btree-Shell automatisch den momentanen Datensatz-Inhalt auf der Festplatte in den Tempbuffer eingelesen. Wenn nun Savebuffer (also quasi alter Zustand) und Tempbuffer (Zustand beim Abspeichern, also später) Differenzen aufwiesen, z.B. weil anderer User schneller war, dann wurde die Variable IGAlreadyChanged auf true gesetzt und man konnte reagieren.

Das hiesse dann, man überschreibt die von anderen gemachten Änderungen, oder speichert nicht oder es werden nur einzelne Felder geändert und dann wird gespeichert. Für letzteres u.ä. gab es viele Funktionen. Tja, finde das Prinzip immer noch wasserdicht.

mkinzler 5. Nov 2015 11:52

AW: Servergeänderte Datensätze
 
So funktioniert es grundsätzlich heute auch noch in auf Versionierung basierenden Transaktionssteuerungen.

Hansa 5. Nov 2015 12:01

AW: Servergeänderte Datensätze
 
Ja, im Prinzip. Aber erkläre das doch mal, wie man die Transaktionen einstellen muss und was sonst noch zu beachten ist. Die Aussage "funktioniert heute noch so", die nützt dem Fragesteller nämlich nichts.

mkinzler 5. Nov 2015 12:08

AW: Servergeänderte Datensätze
 
Wie es bei dem Produkt vor 30 Jahren war, noch weniger.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz