Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Paradox-Datenbanken im Netzwerk nutzen (https://www.delphipraxis.net/5455-paradox-datenbanken-im-netzwerk-nutzen.html)

eddy 6. Jun 2003 22:17


Paradox-Datenbanken im Netzwerk nutzen
 
Hallo MrSpock,

ich wende mich gleich an Sie, da ich aus den bereits vorhandenen Beiträgen herausgelesen habe, daß Sie Paradox-DB im Netz erfolgreich verwenden. (Natürlich nehme ich gern auch Hilfe von jedem anderen Nutzer dieses Forums an!)

Ich habe seit mehr als einem Jahr eine kleine Anwendung zur Adressen-, Artikel- und Projektverwaltung in Benutzung, die auf Paradox-DB basiert. Funktioniert so halbwegs, Tools zur Fehlersuche, automatischer Indexerzeugung usw. habe ich mir auch geschaffen.

Aufgrund diverser räumlicher Änderungen ist nun ein zweiter PC dazu gekommen, mit dem ich auf die gleichen Datenbestände zugreifen will.

Zum Test im Netzwerk habe ich folgende Komponenten angelegt:
DS1 : TDataSource (lies DS-Eins)
Tab1 : TTable
DB1 : TDatabase
Sess1 : TSession

Die Anzeige der Daten erfolgt in einem TDBGrid

Über einen Button erfolgt die Aktivierung:
Code:
procedure TForm1.sbAktivierenClick(Sender: TObject);
begin
  DB1.Connected := false;
  Sess1.Active := false;
  Tab1.Active := false;

  Tab1.DatabaseName := Edit1.Text;    // c:\adr\daten oder m:\adr\daten
  Tab1.SessionName := Sess1.SessionName;
  Tab1.TableName := fnAdr; //Adressen.DB

  DS1.DataSet := Tab1;

  DBGrid1.DataSource := DS1;

  DB1.DatabaseName := Edit1.Text; // c:\adr\daten oder m:\adr\daten
  DB1.SessionName := Sess1.SessionName;
  DB1.TransIsolation := tiDirtyRead;

  // während OnActivate wird in Abhängigkeit vom PC
  //   zuvor Sess1.NetFileDir zugewiesen
  // PC mit Datenbank: C:\adr\daten
  // PC ohne Daten: M:\adr\daten

  Sess1.Active := true;
  DB1.Connected := true;
  Tab1.Active := true;
end;
Die Adress-DB enthält einen Primär-Index ID (AutoInc) sowie einen Sekundär-Index Such (A, 40).

Auf beiden PC's erfolgt die Anzeige der Tabelle. Ich ändere auf einem der beiden PC's den aktuellen Suchbegriff von "Test" auf "Testxxxxxx" um und wechsle zum nächsten Datensatz.

Auf dem anderen PC bleibt aber "Test" stehen. Und damit bin ich bei meinem Problem angekommen: wie bringe ich meine Anwendung dazu, daß die Änderungen umgehend nach Wechsel des Datensatzes (und somit dem Abschluß der Änderungenen in diesem Satz) auf dem jeweils anderen PC angezeigt werden?


mfg
eddy

Specialwork 7. Jun 2003 00:00

OnUpdateRecord
 
Hallo Eddy,

Ich bin mir zwar nicht sicher, aber Du solltest Dir das Ereignis
Delphi-Quellcode:
TQuery.OnUpdateRecord
oder
Delphi-Quellcode:
TTable.OnUpdateRecord
in der Hilfe mal anschauen.

Gruß, Tom

r_kerber 7. Jun 2003 09:08

@Eddy: das, was Du hier beschreibst ist kein Problem von Paradox allein. Dies kann immer auftreten IMHO immer auf, wenn man mit Datenbanken arbeitet, auf die mehrere User gleichzeitig zugreifen. Die Daten, die Du im DBGrid siehst sind immer nur eine Momentaufnahme. Änderst ein ein User einen Datensatz, dann sehen das die anderen zunächst nicht sondern erst wenn dieser Datensatz erneut von der DB gelesen wird.
@Specialwork: Dieses Ereignis tritt ein, wenn in der lokalen Kopie ein Datensatz geändert wird, ist also keine Lösung für das geschilderte Problem.

woki 7. Jun 2003 09:48

@eddy:

Wie r_kerber schon sagte, die Datenbank (weder diese noch andere) übernimmt diese Funktion nicht, und schaut man sich die Philosophie relationaler Datenbanken an, erkennt man, daß sie das auch nicht kaum kann. Wenn das wirklich nötig ist, und ein regelmäßiges Abholen der Daten nicht reicht, wird man einen "Messagingmechnismus" implementieren müssen, über den die Clients sich über erfolgte Datenmodifikationen verständigen, aber ich kann mir nicht vorstellen, daß der Aufwand gerechtfertigt ist.

Gruß
Woki

r_kerber 7. Jun 2003 09:53

Vielleicht sollte Eddy mal erläutern, wobei ihn dieses Verhalten stört, dann könnte man vieleicht ein paar Tips geben. Die schlechte Lösung ist IMHO ein regelmäßiges automatisches aktualisieren der Daten auf den Clients, da dies nur unnötigen Datenverkehr im Netz erzeugt!

Mitchl55 7. Jun 2003 10:03

Hallo,

ich habe mit derselben Problematik zu tun. Bisher wird es so gelöst, das das Programm wenn es nicht benötigt wird einfach geschlossen wird und wenn es wieder benötigt wird erneut geöffnet! Blöde Sache und eigentlich nicht im Sinne des Erfinders.

Im Augenblick habe ich nicht die Zeit um eine Idee auszuprobieren, aber vielleicht hilft sie Dir ja weiter oder jemand kann sofort sagen das dieses nicht funktioniert!

Beispiel:

Wenn ich eine Form in einem Programm eingebunden habe, in der Editfelder, Comboboxen (Datenbanken) etc. vorhanden sind in denen ich Dinge eingetragen und ausgewählt habe bleiben bei jedem Aufruf der Form die alten Einstellungen erhalten nur wenn ich das Programm einmal beende und wieder neu starte habe ich die Form wie ich sie programmiert habe! Das ist glaube ich ein Problem ob die Form zur Laufzeit erzeugt wird oder erst wenn ich diese benötige.
http://www.delphipraxis.net/internal_redirect.php?t=3622&highlight=form+erzeug en

Also wäre es doch den Versuch Wert zu überprüfen, ob es etwas bringt, die Form jedesmal komplett zu schliessen und wieder neu zu erzeugen - hier ist es aber nicht mit FormX.close und FormX.open getan wenn ich das richtig verstanden habe... und vieleicht hilft Dir ja dir herausgesuchte Eintrag weiter.

Könnte klappen?... Halt mich auf dem Laufenden...

Gruß

Mitchl

MrSpock 8. Jun 2003 10:10

Hallo eddy,

geht es dir jetzt darum, dass du die Änderung, die ein anderer Nutzer gemacht hast mitbekommst oder sogar, dass der aktuelle Datensatz in beiden Anwendungen sychron bleibt?

Das zweite ist natürlich nicht so einfach.

Ansonsten hat die r_kerber bereits erklärt, was das Problem ist. Bei einer Desktop Datenbank wie Paradox wird ja eine Kopie der gesamten Tabelle übers Netz geschoben, wenn du darauf zugreifst. Du kannst also nicht sofort mitbekommen, wenn ein anderer Nutzer einen Datensatz ändert.

Die Zuweisung von Werten an bestimmte Eigenschaften, sorgt für ein update.
Wenn du z.B. der Eigenschaft "Filtered" der Tabelle eine Wert zuweist, wird die Tabelle "upgedated". Weise einfach mal dem Event AfterScroll von z.B. Table1 den folgenden Code zu:

Delphi-Quellcode:
Table1.Filtered := Table1.Filtered;
Dann wird jedem Scroll Event die Änderungen von anderen angezeigt.

eddy 8. Jun 2003 15:01

Hallo Leute,

vielen Dank für Eure schnelle Anteilnahme. Da hab' ich mir ja wohl eine schwere Nuß zum Knacken rausgesucht.

Kann mir mal noch jemand verraten, was IMHO heißt? Ist bestimmt ganz einfach, wenn man's weiß.

Die im Beispiel genannten Änderungen sind ein ärgerliches Übel. Wenn ein Nutzer eine Änderung vornimmt, erscheint diese nicht. Noch extremer und richtig störend wird es aber erst, wenn Datensätze gelöscht oder hinzugefügt werden.

Ich habe ein bischen herumprobiert. Mit folgendem Code, z.Zt. noch über einen Button zu aktivieren, wird DBGrid akutallisiert.

Code:
procedure TForm1.sbRefreshClick(Sender: TObject);
var
  aktrec : integer;
begin
  Screen.Cursor := crHourGlass;
  Tab.DisableControls;
  aktrec := Tab.RecNo;
  Tab.Active := false;
  Tab.Active := true;
  Tab.RecNo := aktrec;
  Tab.EnableControls;
  Screen.Cursor := crDefault;
end;
Gibt es eigentlich einen Unterschied zwischen Tab.Active := true und Tab.Open?

Sobald sbRefresh gedrückt wird, erfolgt die gewünschte Aktuallisierung.

@MrSpock:
Code:
Table1.Filtered := Table1.Filtered;
ändert ja eigentlich gar nichts, aber nachdem ich die Einfügung in Tab1AfterScroll vorgenommen habe, läuft das Testprogramm nicht mehr. AfterScroll wird nicht mehr verlassen (F7) und irgenwann gibt's einen Stack-Überlauf.

Es kann doch nicht sein, daß man sich um solche Dinge auch noch selbst kümmern muß - oder doch? Ich war immer der Meinung, daß Netzwerkfähigkeit bedeutet, daß solche Dinge automatisch ablaufen.

mfg
eddy

r_kerber 8. Jun 2003 18:49

Zitat:

Zitat von eddy
Kann mir mal noch jemand verraten, was IMHO heißt?

in my humble opinion - meiner bescheidenen Meinung nach
Noch Abkürzungen findest Du hier DFÜ-Token und Smileys
Zitat:

Zitat von eddy
Gibt es eigentlich einen Unterschied zwischen Tab.Active := true und Tab.Open?

Habe ich hier schon mal kurz erläutert.

MrSpock 8. Jun 2003 19:31

Hallo eddy,

Zitat:

@MrSpock:
Code:
Table1.Filtered := Table1.Filtered;
ändert ja eigentlich gar nichts,
Das ist richtig, aber als Nebeneffekt wird die Tabelle upgedated. Es wäre auch möglich mit Table1.Close; Table1.Open; dasselbe zu erreichen, dann musst du dir aber die alte Position merken und diese wieder einstellen und zusätzlich, damit man davon nicht sieht mit DisableControls bzw. EnableControls verhindern, dass das Grid etwas davon anzeigt. Deshalb habe ich mit der Zuweisung nichts geändert, sondern nur ein Update erzwingen wollen. (Bei mir funktioniert es auch.) Bei dir wird offensichtlich das Scrollevent immer wieder erzeugt, wenn die Tabelle upgedatet wird, auch dort könnte man noch tricksen, aber in diesem Fall ist vielleicht das o.g. Vorgehen vorzuziehen.

Das Netz kann das für dich ja nicht so einfach machen, da du ja nur auf eine Momentaufnahme schaust. Um zu verhindern, dass bei jedem Scrollevent ein Update stattfindet, könntest du auch folgendes machen. Immer wenn ein Datensatz geändert oder hinzugefügt wurde (z.B. im AfterPost) könntest du die aktuelle Zeit in eine Tabelle im Netz eintragen. Im AfterSroll schaust du dann in diese Tabelle. Ist daie Zeit neuer als die letzte Änderung, die du schon mitbekommen hast, ist ein Update nicht notwendig, sonst machst du das Update wie oben beschrieben.

eddy 8. Jun 2003 19:35

Hallor r_kerber,

vielen Dank für den Link, damit haben sich gleich noch ein paar andere UZK's (= Unidentifizierte ZeichenKetten) geklärt.

Ich hab' die Seite mit DFÜ-Token und Smileys gleich mal in meine Favoriten gelegt. Werd' ich mir nie merken!

mfg
eddy

praktiker 9. Jun 2003 08:00

Hallo Eddi,
Leider habe ich kein Netzwerk aufgebaut und kann meine Theorien nicht austesten. Trotzdem solltest du die nachfolgende Info mal näher anschauen.

Wenn Datensätze innerhalb eines Programmes verändert werden, werden diese erst auf der Platte gespeichert, wenn die Tabelle geschlossen wird. Die veränderten Daten werden in einem Zwischenspeicher gehalten. Vielleicht ist das ja schon der erste Ansatz für das Problem


Erzwingen kann mann diesen Vorgang auch, indem man beim Programmstart folgenden Code in sein Formular einbindet.



uses ...,bde;

type
TFormTest = class(TForm)
........
private
procedure FlashToTable(Sender:TObject; var done:boolean);
.....
end;

procedure TFormTest.flashtotable;
begin
dbiuseidletime;
done:=true;
end;


Abschließend noch im Objectinspector zur Form
eine ONCREATE Anweisung doppelt anclicken und den CODE

procedure TFormTest.FormCreate(Sender: TObject);
begin
application.onidle := FlashToTable;
....
end;

einfügen.


Jetzt speichert das Programm, wenn es nicht anderweitig beschäftigt ist die Daten aus dem Zwischenspeicher direkt auf die Platte.

Mitchl55 9. Jun 2003 12:34

@Praktiker

Genau diese Vermutung hatte ich auch. Die Tabellen werden erst in den Speicher geschrieben und wenn die Tabellen/Programm geschlossen werden, dann werden diese auch auf die Platte geschrieben! Das sieht man auch daran, das bei einem Reset während das Programm läuft alle neu eingetragenen Daten verloren gehen!

@Eddy

Ich weiß´es ja nicht genau, aber ich denke meine Lösung beschreibt Dein Problem (so wie es sich anhört) und gibt Dir die Lösung dazu!

Gruß

Mitchl

eddy 9. Jun 2003 17:25

Hallo Leute!

@praktiker:

Den Verdacht, daß die Zwischenspeicherung der Daten die Aktuallisierung verhindert, hatte ich auch schon.

Zu Testzwecken hatte ich DbiSaveChanges in AfterPost eingebunden. Das hat aber mein Problem nicht gelöst.

Wenn ich mir zu DBiUseIdleTime die Hilfe hole, erhalte ich folgenden Hinweis: This function is no longer supported. Use DbiSaveChanges instead.

Mit application.onidle muß ich mich noch beschäftigen. Zumindest ließe sich damit wohl der Zeitpunkt, wann die Aktuallisierungsabfrage erfolgen soll (in welcher Variante auch immer), festlegen - nämlich wenn das Programm gerade nichts macht.


@MrSpock:

Ich verwende Delphi 5 Professional, könnte das die Ursache dafür sein, daß die Variante mit "Table1.Filtered := Table1.Filtered;" bei mir nicht funktioniert? Schließlich würde diese Variante mein Problem mit dem geringsten Aufwand aus der Welt schaffen.

Die Variante mir der separaten Tabelle, ich habe sie NetCtrl genannt, ist bereits in Arbeit. Aber bevor ich da zuviel Energie 'reinstecke, wollte ich mich hier um Alternativen kümmern.


@Mitchl55:
Den Link habe ich mir angesehen, kann aber keine Verbindung zu meinem Problem herstellen. Das TForm zu schließen und neu zu generieren kommt nicht in Frage, da ja damit die gesamte Initialisierungen und aktuellen Zustände verloren gingen, alle aktuell offenen Datenbanken geschlossen und an der selben Stelle neu geöffnet werden müssen. Erscheint mir vom Zeitverhalten nicht unbedingt optimal.


@

Kann jemand etwas zu dem Zeitbedarf bzw. der Netzwerkbelastung zu den in der bereits beschriebenen Prozedur sbRefreshClick verwendeten Befehlen sagen?

Gibt es noch andere Möglichkeiten, das Updaten der Datenbank, wie von MrSpock beschrieben, zu erzwingen?

mfg
eddy

MrSpock 9. Jun 2003 17:40

Hallo eddy,

nein, ich bin mir ziemlich sicher, dass es nicht an der Version liegt. Ich denke eher, dass nach dieser Zuweisung erneut das Scroll Event erzeugt wird. Das war in meinem kleinen Testprogramm nicht der Fall. Da gibt es jetzt 2 Möglichkeiten. Die eine mit dem Schließen und Wiederöffnen der Tabelle mit einem DisableControls vorher und dem Merken des aktuellen Datensatzes, damit du ihn wieder findest, habe ich ja schon erwähnt. Die andere wäre, dass du die Zuweisung nur machst, wenn das "Tag" der Tabelle 0 ist. Vor der Zuweisung setzt du das Tag dann aber auf 1, so dass bei einer erneuten Auslösung des Scrollevents keine Endlosschleife erzeugt wird, etwa so:

Delphi-Quellcode:
if Table1.Tag = 0 then
begin
   Table1.Tag := 1;
   Table1.Filtered := Table1.Filtered;
end
else { Tag ist 1 }
   Table1.Tag := 0;
Dabei solltest du aber sicher sein, dass das Scroll Event bei der Zuweisung immer ausgelöst wird.

Mitchl55 13. Jun 2003 16:29

Hallo,...

Hab die Antwort von MrSpock ausprobiert! Funktioniert nicht ganz so wie gedacht, ist aber nah dran! Könnte es daran liegen das ich einfach das Programm zweimal gestartet habe!? Oder warum scrollt es öfter? Hab noch zu wenig Ahnung davon!

Gruß

Mitchl


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:42 Uhr.

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