Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Exception richtig behandeln (https://www.delphipraxis.net/141185-exception-richtig-behandeln.html)

Jens Hartmann 4. Okt 2009 12:30


Exception richtig behandeln
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo zusammen,

ich habe mal eine Frage zur Behandlung von Exceptions. Ich lese Daten aus einer Textdatei in eine Datenbank ein.

Wenn jetzt z.B. Das eingelesen Datum kein gültigen Datumswert hat, wird natürlich eine Meldung beim eintragen in die Datenbank erzeugt, die mir sagt, '' ist kein gültiges Datum. (siehe Anhang). Wie kann ich jetzt in mein Commit eine sauber Exeptionbehandlung einbauen, die diese Datensätze einfach nicht übernimmt.

Probiert habe ich das ganz so, funktioniert aber leider nicht.

Delphi-Quellcode:
  VST.BeginUpdate;
  for i := 0 to High(Parser.EntriesMB256) do begin
  Daten := TOMBSerie.Create;
  with Daten do
  begin
  DM_PS.Qry_InsertMB256.Close;
  DM_PS.QryImportMB256.ParamByName('LfdNr').AsInteger := Parser.EntriesMB256[i].LfdNr;
  DM_PS.QryImportMB256.ParamByName('Datum').AsDate := StrToDate(Parser.EntriesMB256[i].Datum);
  DM_PS.QryImportMB256.ParamByName('Uhrzeit').AsTime := StrToTime(Parser.EntriesMB256[i].Uhrzeit);
  DM_PS.QryImportMB256.ParamByName('Ereignis').AsString := Parser.EntriesMB256[i].Ereignis;
  DM_PS.QryImportMB256.ParamByName('Teilnehmer').AsString := Parser.EntriesMB256[i].Teilnehmer;
  DM_PS.QryImportMB256.ParamByName('Bereich').AsString := Parser.EntriesMB256[i].Bereich;

  DM_PS.QryImportMB256.ExecSQL;

  try

    DM_PS.ConPSSecur.Commit;
    DM_PS.QrySelectMaxIDMB256.Open;

  except
    on e : Exception Do begin
      ShowMessage(e.Message);
      end;

  end;



    Daten.ID := DM_PS.QrySelectMaxIDMB256.FieldByName('ID').AsInteger;
    Daten.LfdNr := Parser.EntriesMB256[i].LfdNr;
    Daten.Datum := Parser.EntriesMB256[i].Datum;
    Daten.Uhrzeit := Parser.EntriesMB256[i].Uhrzeit;
    Daten.Ereignis := Parser.EntriesMB256[i].Ereignis;
    Daten.Teilnehmer := Parser.EntriesMB256[i].Teilnehmer;
    Daten.Bereich := Parser.EntriesMB256[i].Bereich;
  end;
  VST.AddChild(nil, Daten);
  DM_PS.QrySelectMaxIDMB256.Close;
  Label6.Caption := IntToStr(StrToInt(Label6.Caption)+1);
  ProgBarDatei.Position := ID;
  Inc(ID);
  VST.ScrollIntoView(VST.GetLast, true);
  VST.EndUpdate;

  DM_PS.QrySelectMaxIDMB256.Close;
  end;
end;
Danke schon mal und Gruß

Jens

jaenicke 4. Okt 2009 12:37

Re: Exception richtig behandeln
 
Der Fehler tritt ja beim StrToDate auf, das jedoch fängst du gar nicht ab. Du solltest lieber mit TryStrToDate usw. arbeiten, dann kannst du bei nicht erfolgreicher Umwandlung auch die Eintragung gar nicht erst versuchen.

alzaimar 4. Okt 2009 12:51

Re: Exception richtig behandeln
 
Grundsätzlich sollten solche Funktionen nur mit garantiert gültigen Parametern aufgerufen werden. Das bedeutet für Dich, das du eine Sicherheitsschicht um diese eigentliche Funktion bauen musst. Diese Sicherheitsschicht nimmt die Parameter entgegen, prüft sie und wirft ggf eine Exception. Erst bei Korrektheit wird die Funktion aufgerufen. Diese kann dann wieder Fehler verursachen, die dann aber isoliert und 'in Ruhe' betrachtet werden können.

sx2008 4. Okt 2009 12:55

Re: Exception richtig behandeln
 
Ich würde an deiner Stelle eine StringListe erzeugen oder der Funktion von Aussen übergeben um darin alle Fehlermeldungen zu sammeln.
Delphi-Quellcode:
except
  on e : Exception Do
  begin
    fehlerliste.Add(Format('Entry %d: %s|%s',[i, e.Classname, e.Message]));
  end;
end;
Die Fehlerliste wird dem Benutzer am Ende präsentiert ohne dass der Benutzer jeden Fehler einzeln quittieren muss.
(ein riesen Vorteil, wenn es mal 50 oder mehr Fehler werden sollten)
Ausserdem wird auch die Entry-Nummer festgehalten; das ist wichtig, wenn man die Ursache der Fehler herausfinden möchte.

Jens Hartmann 4. Okt 2009 14:06

Re: Exception richtig behandeln
 
Hallo,

also irgendwie zue ich mir mit Exceptionbehandlungen noch sehr schwer. Ich habe die jetzt geändert, aber der Fehler ist immer noch da. Hier mal mein neuer Code.

Delphi-Quellcode:
  try
  DM_PS.Qry_InsertMB256.Close;
  DM_PS.QryImportMB256.ParamByName('LfdNr').AsInteger := Parser.EntriesMB256[i].LfdNr;
  DM_PS.QryImportMB256.ParamByName('Datum').AsDate := StrToDate(Parser.EntriesMB256[i].Datum);
  DM_PS.QryImportMB256.ParamByName('Uhrzeit').AsTime := StrToTime(Parser.EntriesMB256[i].Uhrzeit);
  DM_PS.QryImportMB256.ParamByName('Ereignis').AsString := Parser.EntriesMB256[i].Ereignis;
  DM_PS.QryImportMB256.ParamByName('Teilnehmer').AsString := Parser.EntriesMB256[i].Teilnehmer;
  DM_PS.QryImportMB256.ParamByName('Bereich').AsString := Parser.EntriesMB256[i].Bereich;

  DM_PS.QryImportMB256.ExecSQL;
  DM_PS.ConPSSecur.Commit;
  except
    on e : Exception Do
      begin
        Fehlerliste.Add(Format('Entry %d: %s|%s',[i, e.Classname, e.Message]));
      end;
    end;
Vieleicht kann mir ja mal jemand sagen, wo der Fehler liegt, und mal erklären, wie ich am besten an eine solch Try/Except Sache dran gehe.

Danke schon aml

Gruß Jens

jaenicke 4. Okt 2009 15:22

Re: Exception richtig behandeln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Was heißt der Fehler ist noch da? Dass Delphi den anzeigt, wenn du das Programm aus Delphi startest? Das passiert immer, wenn der Debugger aktiv ist.

Um das zu verhindern, kannst du (wenn der Fehler angezeigt wird) dessen Anzeige einfach mit der CheckBox deaktivieren. (Siehe Anhang)
Oder einfach das Programm nicht aus Delphi sondern separat starten (Menü Start --> Ohne Debugger ausführen).

// EDIT:
Auf TryStrToDate stattdessen habe ich ja schon hingewiesen, das wäre noch besser...

Jens Hartmann 4. Okt 2009 15:43

Re: Exception richtig behandeln
 
Liste der Anhänge anzeigen (Anzahl: 3)
Das ist mir schon klar.

Der Fehler, kommt aber auch, wenn ich ohne Debugger ausführe, da ja ein Fehler vorhanden ist. Ich muss ja realisieren, wodurch der Fehler kommt, um diesen dann auszuschliessen. Nur wenn ich im Debugger auf Anhalten klicke, um an die Stelle im Code zu gelangen, wo der Fehler passiert, lande ich irgendwo im Quellcode der ZEOS Kompo und wieß jetzt nicht, wie ich anfangen kann diesen Abzufangen.

Hier nochmal die Fehlermeldungen und der Code in dem ich bei Anhalten lande.

Delphi-Quellcode:
procedure CheckInterbase6Error(PlainDriver: IZInterbasePlainDriver;
  StatusVector: TARRAY_ISC_STATUS; LoggingCategory: TZLoggingCategory = lcOther;
  SQL: string = '');
var
  Msg: array[0..1024] of Char;
  PStatusVector: PISC_STATUS;
  ErrorMessage, ErrorSqlMessage: string;
  ErrorCode: LongInt;
begin
  if (StatusVector[0] = 1) and (StatusVector[1] > 0) then
  begin
    ErrorMessage:='';
    PStatusVector := @StatusVector;
    while PlainDriver.isc_interprete(Msg, @PStatusVector) > 0 do
      ErrorMessage := ErrorMessage + ' ' + StrPas(Msg);

    ErrorCode := PlainDriver.isc_sqlcode(@StatusVector);
    PlainDriver.isc_sql_interprete(ErrorCode, Msg, 1024);
    ErrorSqlMessage := StrPas(Msg);

{$IFDEF INTERBASE_EXTENDED_MESSAGES}
    if SQL <> '' then
      SQL := Format(' The SQL: %s; ', [SQL]);
{$ENDIF}

    if ErrorMessage <> '' then
    begin
      DriverManager.LogError(LoggingCategory, PlainDriver.GetProtocol,
        ErrorMessage, ErrorCode, ErrorSqlMessage + SQL);

{$IFDEF INTERBASE_EXTENDED_MESSAGES}
      raise EZSQLException.CreateWithCode(ErrorCode,
        Format('SQL Error: %s. Error Code: %d. %s',
        [ErrorMessage, ErrorCode, ErrorSqlMessage]) + SQL);

Zitat:

Zitat von jaenicke
Auf TryStrToDate stattdessen habe ich ja schon hingewiesen, das wäre noch besser...

Und das versteh ich noch nicht so ganz.

MFG

jens

haentschman 4. Okt 2009 15:56

Re: Exception richtig behandeln
 
Hallo Jens,

Exception 2: Erklärt sich von selbst. irgendwo, wo ein Date Wert sein sollte ist nix.
Exception 1: Kommt ganz gern, wenn die Länge des Strings die Feldgröße überschreitet.

die Zugriffsverletztung :gruebel:

jaenicke 4. Okt 2009 15:59

Re: Exception richtig behandeln
 
Zitat:

Zitat von Jens Hartmann
Und das versteh ich noch nicht so ganz.

Der Umwandlungsfehler wird bei dem StrToDate kommen. Und das kannst du vorher prüfen:
Delphi-Quellcode:
var
  DateValue: TDate;
begin
  ...
  if not TryStrToDate(DeinString, DateValue) then
  begin
    ShowMessage('Fehler bei Umwandlung von ' + DeinString + ' in einen Datumswert');
    Exit; // abbrechen oder so
  end;
  ...
  // Wenn alles erfolgreich war, dann die Werte benutzen:
  DateValue ...
// EDIT:
Ja, ich weiß, Exit ist nicht unbedingt ein schöner Programmfluss, kann man natürlich auch umgekehrt formulieren.

Zu den SQL-Fehlern sage ich mangels Erfahrung lieber nix. :mrgreen:

DeddyH 4. Okt 2009 16:06

Re: Exception richtig behandeln
 
Zitat:

Delphi-Quellcode:
DM_PS.Qry_InsertMB256.Close;
...
DM_PS.ConPSSecur.Commit;

Machst Du das wirklich bei jedem Datensatz? Und wenn im Erfolgsfall ein Commit erfolgen werden soll, muss im Fehlerfall ja wohl ein Rollback erfolgen (und dann eine neue Transaktion gestartet werden). Ansonsten wie angesprochen vorher auf gültiges Datum/Uhrzeit prüfen, im Fehlerfall loggen und zum nächsten Datensatz.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:28 Uhr.
Seite 1 von 4  1 23     Letzte »    

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