Entwickler-Ecke

Datenbanken - Bestimmen welche ADOQuery eine Exception auslöst


Nico B. - Fr 15.11.13 13:54
Titel: Bestimmen welche ADOQuery eine Exception auslöst
Hallo liebe Helferlein,

in meinem Programm arbeite ich mit mehreren ADOQuery's.
In der Exceptionbehandlung würde ich nun gern bei einer fehlerhaften SQL-Anweisung herausbekommen, durch welche ADOQuery die Exception ausgelöst wurde, um mir deren SQL-Anweisung in ein Fehlerlog zu speichern.

Gibt es eine Möglichkeit das herauszubekommen?

Vielen Dank schon mal.

Nico


Delete - Fr 15.11.13 14:15

Wie wär's mit einem Try-Except-Block?


Nico B. - Fr 15.11.13 14:25

Hallo Perlsau,

ich würde das gern allgemeiner lösen.
In meinem Programm habe ich viele SQL-Abfrage über die Query´s.
Da ich finde, dass das Programm schnell unübersichtlich wird, wenn ich jede Abfrage mit einem Try-Except-Block umschließe, habe ich das OnException-Event des Application-Objekts für eine allgemeine Exception-Behandlung genutzt.
In diesem Event suche ich nun eine Möglichkeit herauszubekommen, welche ADOQuery die Exception ausgelöst hat.


Delete - Sa 16.11.13 13:42

Doch weil dein Quellcode streng geheim ist, können wir uns das nicht auch mal aus der Nähe anschauen, denn schließlich geht es hier ja um Firmengeheimnisse und Datenschutz. Schade, ich hätte dir gerne geholfen ...


Nico B. - So 17.11.13 10:32

Hallo Perlsau,

habe ich da eben etwas verpasst?
Das Programm schreibe ich für meine Arbeit, das ist richtig.
Aber ich habe nirgends gelesen, dass man sich deshalb hier nicht helfen lassen darf...
Und nach dem Quellcode gefragt hatte bisher auch noch niemand.

Ich habe den Quellcode nicht gepostet, weil er eben doch etwas umfangreicher ist.
Ich weiß nicht, wo ich da anfangen soll und wo aufhören.

Wie ich ja bereits geschrieben habe, nutze ich die try-except-Blöcke eben nicht, weil mir das zu viel wird.
Ich gebe aber gern ein Beispiel.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
adoq1: TADOQuery;
adoq2: TADOQuery;
adoq3: TADOQuery;

procedure oncreate
begin
  adoq1.close;
  adoq1.sql.clear;
  adoq1.sql.append('select * from tabelle1');
  adoq1.execsql;
  adoq2.close;
  adoq2.sql.clear;
  adoq2.sql.append('select * from tabelle2');
  adoq2.execsql;
  adoq3.close;
  adoq3.sql.clear;
  adoq3.sql.append('update tabelle1');
  adoq3.execsql;
  adoq1.close;
  adoq1.sql.clear;
  adoq1.sql.append('select * from tabelle1');
  adoq1.execsql;
end;

procedure appexception(sender: tobject; e: exception);
begin
  if e.classname=EOLEException
    then
      begin
        //hier soll nun herausgefunden werden, welche ADOQuery die Exception ausgelöst hat
        //anschließend soll deren SQL-Statement zur späteren Fehleranalyse in einer Textdatei gespeichert werden
      end;
end;


Hat jemand Ideen wie man die entsprechende ADOQuery identifiziert?


Delete - So 17.11.13 12:12

Ist mir zuviel.


WasWeißDennIch - So 17.11.13 12:18

Könnte der Sender evtl. die fehlerauslösende Komponente sein? Irgendeinen Sinn muss der Parameter ja haben.


Nico B. - So 17.11.13 19:49

Hallo WasWeißDennIch,

das hatte ich auch gedacht.
Leider verweist der Sender jedoch immer auf meine Hauptform.


Quitzlinga - Mo 18.11.13 00:12

Hi,

schreib dir doch einfach eine Funktion, über die Du die jeweiligen SQL-Befehle abschickst. Da kannst Du dann gleichzeitig die Auswertung machen und sparst Dir überflüssigen Code.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
function DoSQL(aAdoCon : TAdoConnection; aSQL : string) : boolean;
var
  aQuery : TAdoQuery;
begin
  result := false;
  try
    aAdoQuery := TAdoQuery.Create(NIL);
    try
      aAdoQuery.Connection := aAdoCon;
      aAdoQuery.SQL.Add(aSQL);
      result := true;
    except
      on e : exception do begin
        // Hier Fehlerauswertung
      
      end;
    end;
  finally
    aAdoQuery.Close();
    FreeAndNil(aAdoQuery);
  end;
end;


Obige Funktion liefert aber kein Resultset zurück, d.h. es ist nur für Befehle wie INSERT, UPDATE, DELETE etc. Eine Anpassung sollte aber kein Problem sein.

Die Idee, es mit der Applikationsfehlerbehandlung zu machen ist schlecht, da beim erstbesten Fehler Delphi deine OnCreate-Routine verlässt und nicht zurückkehrt. Fang die Fehler besser dort ab,
wo sie auftreten können, dann kannst Du wenigstens noch einen konsitenten Zustand wieder herstellen.

MfG

Quitzlinga


Nico B. - Mo 18.11.13 09:41

Hallo Markus,

das Verlassen der aktuellen Routine durch die AppException ist in meinem Fall nicht so tragisch, da ich mit der laufenden Bearbeitung im Fehlerfall sowieso nicht weitermachen könnte.
Dennoch danke für den Hinweis. Das wusste ich bisher nicht. Werde daher demnächst darauf achten.

Deine Funktion hat mich dennoch auf meine aktuelle Lösung gebracht.
Ich habe mir nun eine ExecSQL-Routine inklusive Fehlerbehandlung geschrieben.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//Fehlermeldung ist eine Prozedur zum Speichern einer Fehlermeldung in eine Logdatei

procedure ADOQExecSQL(ADOQ: TADOQuery);
var
  i: integer;
begin
  try
    ADOQ.ExecSQL;
  except
    Fehlermeldung('Es ist ein Fehler bei der Ausführung einer SQL-Anweisung aufgetreten.');
    for i:=0 to ADOQ.SQL.Count-1 do
      Fehlermeldung(ADOQ.Name+': '+ADOQ.SQL:[i]);
  end;
end;


Diese Prozedur hat für mich den Vorteil, dass sie für alle ADOQuerys gleich aufgerufen werden kann.
In meinem Quellcode brauche ich außerdem nur das ADOQ1.ExecSQL durch ein ADOQExecSQL(ADOQ1) ersetzen.

Vielen Dank!
Nico


baumina - Mo 18.11.13 10:00

Und wenn du noch on e : exception einbaust, kannst du sogar ausgeben lassen um welchen SQL-Fehler es sich handelt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
//Fehlermeldung ist eine Prozedur zum Speichern einer Fehlermeldung in eine Logdatei

procedure ADOQExecSQL(ADOQ: TADOQuery);
var
  i: integer;
begin
  try
    ADOQ.ExecSQL;
  except
    on e : exception do
    begin
      Fehlermeldung('Es ist folgender Fehler bei der Ausführung einer SQL-Anweisung aufgetreten:'+e.Message);
      for i:=0 to ADOQ.SQL.Count-1 do
        Fehlermeldung(ADOQ.Name+': '+ADOQ.SQL:[i]);
    end;
  end;
end;


Nico B. - Mo 18.11.13 10:16

Hallo baumina,

danke für den Hinweis.
Das hatte ich gemacht, hab´s nur irgendwie beim Übertragen des Quellcodes hier ins Forum vergessen.
Sorry.

Nico