Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi ADO (automatische DB Syncronisierung verhindern) (https://www.delphipraxis.net/59190-ado-automatische-db-syncronisierung-verhindern.html)

opfer.der.genauigkeit 19. Dez 2005 10:45

Datenbank: MS-SQL • Zugriff über: ADO

ADO (automatische DB Syncronisierung verhindern)
 
Hi,

es ist fast peinlich zu fragen, aber ich hab da 'n Problem. :oops:
Das ganze passiert mir mit den lustien dbGo-Komponenten (ADO).

Delphi-Quellcode:
  query.edit;
  query.fieldbyname( 'example' ).asstring := 'bla';
  query.close;
Meiner Meinung nach dürfte der neue Text nicht in die Datenbank geschrieben worden sein (erst nach Update bzw. ExecSQL bei Insert etc.).
Tatsächlich verhält sich das leider bei mir grad etwas anders. :gruebel:
Sobald ich einen Wert übergebe, werden die lokalen Daten mit der Datenbank syncronisiert.

Soooo .. es gibt bestimmt ne Einstellung, die ich jedes mal Hilfe lesen übersehen habe.

Danke, ich hasse es an so Kleinigkeiten hängen zu bleiben. :evil:

MfG und thx

//Edit: Crossposting im DF

shmia 19. Dez 2005 12:01

Re: ADO (automatische DB Syncronisierung verhindern)
 
Zitat:

Zitat von opfer.der.genauigkeit
Meiner Meinung nach dürfte der neue Text nicht in die Datenbank geschrieben worden sein (erst nach Update bzw. ExecSQL bei Insert etc.).
Tatsächlich verhält sich das leider bei mir grad etwas anders.

Wenn du recht hast, dann müsste auf jeden Fall das Event "BeforePost" gefeuert werden.
Ich würde da ein ShowMessage in den betreffenden Eventhandler setzen, um das herauszufinden.
Wenn an der Query ein DBGrid dranhängt, könnte das die Ursache für den unbeabsichtigten Post des Datensatzes sein.
Abhilfe:
Delphi-Quellcode:
DBGrid.Options := DBGrid.Options + [dgCancelOnExit]

opfer.der.genauigkeit 19. Dez 2005 12:52

Re: ADO (automatische DB Syncronisierung verhindern)
 
Danke für die Antwort.
Für den Benutzer werden die Daten nur in einer Baumstruktur angezeigt, die nicht
Datenbank gebunden ist.
Irgendwas übersehe ich :wall:

shmia 19. Dez 2005 13:14

Re: ADO (automatische DB Syncronisierung verhindern)
 
Zitat:

Zitat von opfer.der.genauigkeit
Irgendwas übersehe ich :wall:

Genau! du hast nicht überprüft, ob BeforePost und AfterPost abgefeuert wird.

opfer.der.genauigkeit 19. Dez 2005 13:48

Re: ADO (automatische DB Syncronisierung verhindern)
 
Doch, hab ich, aber ich habe vergessen zu sagen, dass ich das getan habe. :stupid:
Beide werden ausgeführt.

shmia 19. Dez 2005 13:56

Re: ADO (automatische DB Syncronisierung verhindern)
 
Zitat:

Zitat von opfer.der.genauigkeit
Doch, hab ich, aber ich habe vergessen zu sagen, dass ich das getan habe. Beide werden ausgeführt.

Also doch. Dann setze mal einen Breakpoint im Eventhandler und lass dir den Aufrufstack anzeigen.
Vorher Compiler-Option "Mit Debug-DCUs" setzen.
So kannst du raus bekommen, ob [ADOQuery].Post aus [ADOQuery].Close heraus aufgerufen wird, oder ob ein Control (DBGrid oder sonstiges) seine Finger im Spiel hat.

opfer.der.genauigkeit 19. Dez 2005 14:42

Re: ADO (automatische DB Syncronisierung verhindern)
 
Ich denke mittlerweile herrausgefunden zu haben woran es liegt.
Ich navigiere in der Datenmenge mit GotoBookmark.
Bei dieser Methode wird intern Resync aufgerufen.

Delphi-Hilfe:
Zitat:

Resync wird intern von den anderen Datenmengenmethoden verwendet, um die Datenmenge bei Änderungen der internen Cursorposition mit den zugrunde liegenden physischen Daten abzugleichen. In Anwendungen sollte die Methode Refresh anstelle von Resync aufgerufen werden.
Mist?
:wiejetzt:

//Edit: die Daten werden immer dann syncronisert wenn ich (abgesehen von first und next) navigiere.

opfer.der.genauigkeit 3. Jan 2006 21:41

Re: ADO (automatische DB Syncronisierung verhindern)
 
Da ich nur ungerne Threads von mir liegen lasse, hier die Lösung:

Das Konzept von ADO hat per Default die Einstellung für implizite Transaktionen.
D.h. werden Daten geändert, werden diese direkt in die DB eingefügt bzw. wie in meinem
Fall durch das Resync abgeglichen.

Um dies zu verhindern muss mit expliziten Transaktionen über das ConnectionObjekt verarbeitet werden.
Dies kann durch den Aufruf von ADOConnection.BeginTrans eingeleitet und bei Bedarf mit CommitTrans oder RollbackTrans beendet werden.

Ich finde diese Regelung etwas seltsam, aber ok... man kann damit leben.

Evtl. kennt jemand noch eine andere Art für eine Lösung. Vielleicht eine noch bequemere? :)

Siehe: http://www.entwickler-forum.de/webx?....0@.4a872c60/0

alzaimar 3. Jan 2006 21:50

Re: ADO (automatische DB Syncronisierung verhindern)
 
Hi,
Das ADO jede Änderung nach Ändern das aktuellen Records speichert, hat Nichts mit Impliziten Transaktionen zu tun. Das macht die BDE genauso, und im Übrigen jeder TDataset-Abkömmling. Das ist doch der Sinn eines TDatasets.

Versuchs mal mit:
Delphi-Quellcode:
Connection.Locktype := ltBatchOptimistic
Damit werden die Änderungen im ADO-Recordset gesammelt. Du kannst die Daten mit ApplyUpdates dann 'im Stapel', also innerhalb einer einzigen Transaktion zum Server blasen oder aber über CancelUpdates (?) wieder verwerfen.

opfer.der.genauigkeit 4. Jan 2006 08:58

Re: ADO (automatische DB Syncronisierung verhindern)
 
Zitat:

Zitat von alzaimar
Hi,
Das ADO jede Änderung nach Ändern das aktuellen Records speichert, hat Nichts mit Impliziten Transaktionen zu tun. Das macht die BDE genauso, und im Übrigen jeder TDataset-Abkömmling. Das ist doch der Sinn eines TDatasets.

Dass die Datensätze automatisch mit der Datenbank abgeglichen werden hat laut MS schon etwas mit impliziten Transaktionen zu tun. Zumindest behaupten das einige Artikel die ich gefunden habe.
Es geht ja eigentlich um die "Default-Einstellung".

Die Änderung auf ltBatchOptimistic hat geholfen. Hättest dich ja auch wirklich mal früher melden können. :mrgreen:
Danke

alzaimar 5. Jan 2006 17:23

Re: ADO (automatische DB Syncronisierung verhindern)
 
Zitat:

Zitat von opfer.der.genauigkeit
Dass die Datensätze automatisch mit der Datenbank abgeglichen werden hat laut MS schon etwas mit impliziten Transaktionen zu tun.

Die "implicit transactions" schlagen erst zu, wenn ein entsprechender (SQL-)Befehl abgesetzt wurde. Die impliziten Transaktionen finden ja auf Serverseite statt.

Per default speichert ein MyDataSet.Post alle Änderungen unmittelbar in der Datenbank. Dein Ansatz ('BeginTransaction') unterbindet das nicht, sondern sagt dem Server nur, das er die Änderungen noch nicht speichern soll. Der Server wird aber mit Befehlen bombardiert, die er sowieso wieder rückgängig machen wird (per Rollback). Schlimmer ist, das -je nach Einstellung des 'Isolation Level'- Tabellen gesperrt werden, sodaß u.U. kein Anderer mehr mit der DB arbeiten kann, bis Du dein Rollback (oder Commit) ausführst.

Transaktionen dienen eigentlich nur zum Kapseln atomarer Operationen. Klassisches Beispiel wäre eine Anwendung, die eine Banküberweisung tätigt. Dann muss die Belastung des einen Kontos und die Gutschrift des anderen Kontos in einer Transaktion gekapselt werden.

Grundsätzlich sollte man die Transaktionen zu kurz wie möglich offen halten, damit eine echte Mehrbenutzerumgebung gewährleistet ist.


Zum Schluss: Entschuldigung, das ich erst so spät antworte. :zwinker: Ich werd' mich gleich mal geißeln... Warte ... :wall:

So, jetzt gehts mir besser

:cheers:


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:19 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 by Thomas Breitkreuz