Entwickler-Ecke

Datenbanken - Transaktions-Bestätigung bei AdoQuery


rob87 - Do 06.11.08 16:26
Titel: Transaktions-Bestätigung bei AdoQuery
Hallo zusammen,

ich hab grad mal ein kleines Problem.
Wenn ich mit einer ADOQuery-Komponente einen Delete mach, muss ich ja nach dem

Delphi-Quelltext
1:
2:
Qry1.ExecSQL;
Qry1.Transaction.Commit;  //  oder so ähnlich ???

auch irgendein CommitRetaining, etc. machen. Aber irgendwie find ich des grad ned. Commit, CommitRetaining, oder Transaction.Commit; gibts beim AdoQuery nicht??

Denn aktuell krieg ich bei einem erneuten Locate-"Versuch" folgende Meldung:
Die zum Aktualisieren angegebene Zeile wurde nicht gefunden. Einige Werte wurden seit dem letzten Lesen ggf. geändert"


alzaimar - Do 06.11.08 16:59

Eine Transaktion muss erstmal gestartet werden. Nach dem Ausführen der Befehle bestätigt man die Ausführung ('Commit') oder verwirft sie ('Rollback'). Mit ADO geht das in etwa so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
ADOConnection.BeginTrans;
Try
  // hier die Datenbankbefehle
  ADOConnection.Commit;
Except
  ADOConnection.Rollback;
  Raise
End;

So oder ähnlich.


rob87 - Do 06.11.08 17:13

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
Eine Transaktion muss erstmal gestartet werden. Nach dem Ausführen der Befehle bestätigt man die Ausführung ('Commit') oder verwirft sie ('Rollback'). Mit ADO geht das in etwa so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
ADOConnection.BeginTrans;
Try
  // hier die Datenbankbefehle
  ADOConnection.Commit;
Except
  ADOConnection.Rollback;
  Raise
End;

So oder ähnlich.


OK. Soweit die Theorie. So wollt ichs ja auch machen. Aber meine TADOQuery-Komponente kennt kein Commit oder Rollback ???
Ich hab mal ne Quellcode-Auszug:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
QryDel: TADOQuery;
//...
QryDel.SQL.Clear;
QryDel.SQL.Text := 'delete from table1';
QryDel.ExecSQL;
//Und hier noch ein Commit oder CommitRetaining   |  eigentlich!

//Das macht er auch wunderbar. Aber wie gesagt, sobald ich dann nun Locate mach, hat er obiges Problem


alzaimar - Fr 07.11.08 09:32

user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
..Aber meine TADOQuery-Komponente kennt kein Commit oder Rollback ???[delphi]
Aber die ADOConnection. Das ist ein eigenes Objekt der Klasse 'TADOConnection'. Bei meinen Projekten habe ich ein TDatamodule, in dem eine TADOConnection und diverse TADOQuery/TADODataset-Komponenten liegen. Alle sind dann mit der TADOConnection verbunden. Hier könntest Du auch eine Zugriffsteuerung (Login) verwenden (LoginPrompt-Eigenschaft).


rob87 - Fr 07.11.08 10:38

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
..Aber meine TADOQuery-Komponente kennt kein Commit oder Rollback ???[delphi]
Aber die ADOConnection. Das ist ein eigenes Objekt der Klasse 'TADOConnection'. Bei meinen Projekten habe ich ein TDatamodule, in dem eine TADOConnection und diverse TADOQuery/TADODataset-Komponenten liegen. Alle sind dann mit der TADOConnection verbunden. Hier könntest Du auch eine Zugriffsteuerung (Login) verwenden (LoginPrompt-Eigenschaft).


Jaja. Is bekannt. Das LoginPrompt dient ja zur USer-Abfrage. Aber des hat ja nix mit dem Transaction.Commit, etx zu tun, oder?


alzaimar - Fr 07.11.08 10:39

Nein, aber es hätte sein können, das Du das Connection-Objekt nicht kennst.


rob87 - Fr 07.11.08 12:03

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
Nein, aber es hätte sein können, das Du das Connection-Objekt nicht kennst.

Doch. doch.

Aber ich kenn halt von TIBQuery die Methoden Transaction.Commit; oder Transaction.CommitRetaining;

Und ich denk, dass ich des nach meinem TAdoQuery1.ExecSQL; auch brauch


alzaimar - Fr 07.11.08 12:08

user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Und ich denk, dass ich des nach meinem TAdoQuery1.ExecSQL; auch brauch

Nein, sondern mein Pattern.


rob87 - Fr 07.11.08 12:25

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Und ich denk, dass ich des nach meinem TAdoQuery1.ExecSQL; auch brauch

Nein, sondern mein Pattern.

Wie meinen? ;-) Ich versteh ned ganz


alzaimar - Fr 07.11.08 13:06


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
ADOConnection.BeginTrans;
Try
  DeineADOQuery.ExecSQL;
  // Hier können noch viel mehr SQL-Anweisungen stehen
  ADOConnection.Commit;
Except
  ADOConnection.Rollback;
  Raise
End;


rob87 - Fr 07.11.08 13:11

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
ADOConnection.BeginTrans;
Try
  DeineADOQuery.ExecSQL;
  // Hier können noch viel mehr SQL-Anweisungen stehen
  ADOConnection.Commit;
Except
  ADOConnection.Rollback;
  Raise
End;


Hmmm... War gut gemeint. Gebracht hats nichts. :-( Es ist nach wie vor so, dass, wenn ich nach dem ExecSQL ein Locate machen will, mein Programm oben genannten Fehler bringt ;-)


alzaimar - Fr 07.11.08 13:19

Gut, das Eine hat mit dem Anderen ja nichts zu tun. Ich hatte die Fehlermeldung gar nicht beachtet, sondern nur Dein Bestreben, eine Transaktion ordendlich abzuwickeln (übrigens ist das bei einer einzigen Zeile, z.B. 'INSERT' oder 'UPDATE' nicht nötig)

Du machst also mit der ADOQuery ein 'DELETE' und versuchst an anderer Stelle dann, diesen Wert zu finden oder wie?


rob87 - Fr 07.11.08 13:53

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
Gut, das Eine hat mit dem Anderen ja nichts zu tun. Ich hatte die Fehlermeldung gar nicht beachtet, sondern nur Dein Bestreben, eine Transaktion ordendlich abzuwickeln (übrigens ist das bei einer einzigen Zeile, z.B. 'INSERT' oder 'UPDATE' nicht nötig)

Du machst also mit der ADOQuery ein 'DELETE' und versuchst an anderer Stelle dann, diesen Wert zu finden oder wie?

Ich mach ein Delete (eines Teilbereiches), und will irgendwann wieder auf die Tabelle zugreifen

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
if Locate( ) = false
then
insert;
//...
else
edit;
//...
end;
post;


alzaimar - Fr 07.11.08 13:59

Und wo kommat das ExecSQL vor?


rob87 - Fr 07.11.08 14:31

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
Und wo kommat das ExecSQL vor?

Des wird davor ausgeführt. Vor diesem Codeschnipsel


alzaimar - Fr 07.11.08 14:34

Ach so. Das Dataset, mit der Du das Locate/Edit/Post machst, weiss doch gar nicht, das Du etwas gelöscht hast. Das der Fehler beim Locate kommt, ist zwar merkwürdig (ich würde beim Post eine entsprechende Fehlermeldung erwarten), aber egal.

Wenn Du z.B. Edit... Post ausführst, wird eine UPDATE-Anweisung generiert und die zum Server geschickt. Normalerweise antwortet der mit 'Danke, ich habe 1 Zeile verändert'. Und ADO ist zufrieden, weil genau das erwartet wurde. Nun wird eine eben gelöschte Zeile per UPDATE verändert. Geht ja nicht, also schickt der Server 'Danke, ich habe 0 Zeilen verändert'. Und dann kommt dieser Fehler.


rob87 - Fr 07.11.08 14:50

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
Ach so. Das Dataset, mit der Du das Locate/Edit/Post machst, weiss doch gar nicht, das Du etwas gelöscht hast. Das der Fehler beim Locate kommt, ist zwar merkwürdig (ich würde beim Post eine entsprechende Fehlermeldung erwarten), aber egal.

Wenn Du z.B. Edit... Post ausführst, wird eine UPDATE-Anweisung generiert und die zum Server geschickt. Normalerweise antwortet der mit 'Danke, ich habe 1 Zeile verändert'. Und ADO ist zufrieden, weil genau das erwartet wurde. Nun wird eine eben gelöschte Zeile per UPDATE verändert. Geht ja nicht, also schickt der Server 'Danke, ich habe 0 Zeilen verändert'. Und dann kommt dieser Fehler.

Aber ich denk dass des bei mir trotzdem noch a bissal anders geregelt is.

Ich hab mehrere Daten in meiner Tabelle. Nun wird ein Teil gelöscht (meinetwegen alle mit dem Wert A im Attribut "Status"). Mittels ExecSQL. Später wird geschaut, ob für den status a schon werte da sind. wenn ja, werden diese überschrieben, wenn nicht eingefügt.


alzaimar - Fr 07.11.08 14:58

user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Aber ich denk dass des bei mir trotzdem noch a bissal anders geregelt is.
Wenn Du meinst.

Nochmal: Das Dataset, mit dem Du suchst, weiss doch gar nicht, das Du per ExecSQL (mit einer anderen Komponente) inzwischen Daten gelöscht hast.
user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Ich hab mehrere Daten in meiner Tabelle.
Definiere 'Tabelle'.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
MyDataset.SQL.Text := 'select * from Tabelle';
MyDataset.Open;

AnotherQuery.SQL.Text := 'delete Tabelle';
AnotherQuery.ExecSQL;

// Preisfrage: Was steht in MyDataset?


rob87 - Fr 07.11.08 15:35

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Aber ich denk dass des bei mir trotzdem noch a bissal anders geregelt is.
Wenn Du meinst.

Nochmal: Das Dataset, mit dem Du suchst, weiss doch gar nicht, das Du per ExecSQL (mit einer anderen Komponente) inzwischen Daten gelöscht hast.
user profile iconrob87 hat folgendes geschrieben Zum zitierten Posting springen:
Ich hab mehrere Daten in meiner Tabelle.
Definiere 'Tabelle'.

Ich mein damit eine Tabelle am MSSQL-Server | Create Table Tabelle1 (id int, textfeld char[20]) oder ähnliches

user profile iconalzaimar hat folgendes geschrieben Zum zitierten Posting springen:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
MyDataset.SQL.Text := 'select * from Tabelle';
MyDataset.Open;

AnotherQuery.SQL.Text := 'delete Tabelle';
AnotherQuery.ExecSQL;

// Preisfrage: Was steht in MyDataset?

Ja nix. Aber ich lösch ja bei mir ned alles aus der Tabelle. Sondern nur einen Teil. Und wenn er eben bei dem rest (der event. noch drinsteht) was findet, editiert er die tabelle nur.

Entweder wir reden aneinander vorbei, oder bei mir hats einfach no ned "Klick" gemacht ;-)


alzaimar - Fr 07.11.08 15:47

Falsche Antwort auf die Preisfrage. Daher hat es noch nicht 'klick' gemacht.

Nach dem 'MyDataset.Open' wird der Inhalt der Tabelle in den Speicher deines PCs geladen. Danach löschst Du auf dem Server die Tabelle. Das 'MyDataset' weiss davon aber Nichts. Woher auch, das hat ihm ja noch niemand gesteckt.

Richtige Antwort: "Die gesamte Tabelle"

Anderes Beispiel:
2xPC (A und B)
A lädt die Tabelle.
B löscht sie.

A weiss davon nix und sieht die Tabelle immer noch auf dem Bildschirm.

Ob A und B zwei PCs oder nur zwei Objekte in deiner Anwendung sind, ändert nix.

Jetzt klar?