Einzelnen Beitrag anzeigen

nahpets
(Gast)

n/a Beiträge
 
#8

Re: Unterschiedliches Verhalten bei Transaktionen

  Alt 15. Sep 2008, 17:06
Hallo Micha,

sorry, aber das kommt mir jetzt spanisch vor:

Zitat:
- wenn ich nem SMALLINT-Feld einen SMALLINT-Wert zuweise und dann ein Post mache, wird die Anweisung angezeigt
Die kommt dann wohl bei der Datenbank an.

Zitat:
- wenn ich nem SMALLINT-Feld einen INTEGER-Wert zuweise und dann ein Post mache, wird diese Anweisung nicht angezeigt
Da tippe ich dann auf die Schnittstelle, die scheint wohl die Sinnhaftigkeit zu prüfen und die Daten dann nicht an die Datenbank weiter zu geben (nach welchen Kriterien mag sie prüfen? Ist aus Entwícklersicht wohl 'ne Blackbox).

Zitat:
--> die 1.Zeile ist danach in der Tabelle drin, die Zweite nicht
Dies wäre ja auch okay, wenn die zweite Anweisung in einer eigenen Transaktion bei der Datenbank ankommt.

Zitat:
- beim SMALLDATETIME-Feld wird die Anweisung sowohl bei nem SMALLDATETIME-Wert als auch bei nem DATETIME-Wert angezeigt,
Hier scheint die Schnittstelle nicht zu prüfen, sondern gibt's an die Datenbank weiter.

Zitat:
Bei beiden Test ist aber auch kein zusätzliches Rollback zusehen, allerdings sehe ich auch das "begin transaction" nicht ???
Gibt es andere Situationen, in denen "begin transaction" und "Commit" bzw. "Rollback" angezeigt werden oder werden die nie angezeigt?

Habe das bei mir mal ausprobiert, kann im SQL-Profiler (wusste bis eben garnicht, dass es sowas gibt ) die Transaktionen sehen. Allerdings habe ich in den Eigenschaften der Ablaufverfolgung die Checkbox "Alle Ereignisse" anzeigen aktiviert und dann im Zweig "Transactions" alles aktiviert.

Wieso ist hier nachher ein Datensatz in der Datenbank?

SQL-Code:
begin transaction

insert into test (a,b,c) values ('01.01.1999',32677,'test');
insert into test (a,b,c) values ('01.01.2099',32677,'test2000');
--insert into test (a,b,c) values ('01.01.1999',32677,'test');
--insert into test (a,b,c) values ('01.01.1999',326770,'test');
--insert into test (a,b,c) values ('01.01.1999',32677,'test1');

commit transaction
wenn das in einer Transaktion abläuft, hätte ich hier keinen erwartet. Das ist meiner Meinung nach ein Fehler der Datenbank, entweder alles aus einer Transaktionsklammer oder nichts.

Hier das gleiche Verhalten:

SQL-Code:
begin transaction

insert into test (a,b,c) values ('01.01.1999',32677,'test');
insert into test (a,b,c) values ('01.01.1999',326770,'test');

commit transaction
Auch das ist meiner Meinung nach nicht korrekt.

Korrekt wäre:

SQL-Code:
begin transaction
insert into test (a,b,c) values ('01.01.1999',32677,'test');
commit transaction

begin transaction
insert into test (a,b,c) values ('01.01.1999',326770,'test');
commit transaction
und anschließend ist der erste Datensatz in der Datenbank, aber das weicht jetzt vom Thema ab, allerdings liegt für meine Begriffe die Vermutung nahe, dass Dein Problem mit diesem Verhalten der Datenbank im Zusammenhang steht.
Das von Dir geschilderte Problem wird mir in diesem Zusammenhang nicht klarer bzw. habe ich momentan keine Ahnung, wie Du um Dein Problem herumkommen kannst (von richtig lösen mag ich garnicht sprechen).

Wie soll man konsistente Daten sicherstellen, wenn sich die Datenbank nicht "erwartungskonform" verhält und zwischen der eigenen Applikation und der Datenbank noch eine Schnittstelle steckt, zu deren "Verhalten im Fehlerfalle" keine Informationen vorliegen?

Habe keine Idee mehr, die Dir bei der Problemlösung helfen könnte.

Zitat:
PS: Wenn ich das mit dem Integer mache, steht auch gar nichts im Error-Record drin !!! So als ob Delphi das Post gar nicht erst ausführen würde und schon eine Exception auslösen tut, bevor es die Daten überhaupt zum SQL-Server schickt. Würde erklären, daß hier kein Rollback ausgeführt wird, da so am SQL-Server ja auch kein Fehler vorliegt.
Der Integer kann "programmintern" schon zu groß sein und deshalb eine Exception auslösen, nicht's im Error-Record = kein Datenbankfehler. Versuch mal im Try Except-Block die Datenbankfehler separat zu behandeln um zwischen Delphi-Fehlern und Datenbankfehlern unterscheiden zu können und mache im Fehlerblock für die Datenbankfehler immer ein Rollback (EDatabaseError wird bei Fehlern der ADO-Komponenten nicht angesprochen, aber EOleException definiert in ComObj).

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
Var
    i : Integer;

begin
  ADOConnection1.Open;
  ADOQuery1.SQL.Clear;
  Memo1.Lines.Clear;
  Try
    ADOQuery1.SQL.Text := memo2.Text;
    ADOConnection1.BeginTrans;
    ADOQuery1.ExecSQL;
    ADOConnection1.CommitTrans;
  Except
    on e : EOleException do begin
      ADOConnection1.RollbackTrans;
      for i := 0 to ADOConnection1.Errors.Count - 1 do begin
        Memo1.Lines.Add(IntToStr(ADOConnection1.Errors.Item[i].Number));
        Memo1.Lines.Add(ADOConnection1.Errors.Item[i].Source);
        Memo1.Lines.Add(ADOConnection1.Errors.Item[i].Description);
        Memo1.Lines.Add((ADOConnection1.Errors.Item[i].SQLState));
        Memo1.Lines.Add(IntToStr(ADOConnection1.Errors.Item[i].NativeError));
      end;
    end;
    on e : Exception Do begin
      ADOConnection1.RollbackTrans;
      ShowMessage(e.Message);
    end;
  end;
  ADOConnection1.Close;
end;
mit dem SQL:
SQL-Code:
delete from test ;
insert into test (a,b,c) values ('01.01.1999',32677,'test');
insert into test (a,b,c) values ('01.01.2099',32677,'test2000');
insert into test (a,b,c) values ('01.01.1999',32677,'test');
insert into test (a,b,c) values ('01.01.1999',326770,'test');
insert into test (a,b,c) values ('01.01.1999',32677,'test1');
In diesem Fall habe ich anschließend zwei Datensätze in der Datenbank.

Offensichtlich hast nicht Du ein Problem, sondern alle haben ein Problem

Kannst Du das Ganze gegen eine andere Datenbank testen (nicht SQL-Server)?

Stephan
  Mit Zitat antworten Zitat