BDE 与 ADO 数据库错误处理

BDE vs ADO Database Error handling

我正在研究 Delphi 7 + SQLserver

BDE中所有与数据库相关的错误都可以使用EDatabaseError

来处理
try

//all database related operations

Except

on EDatabaseError do
begin
  showmessage(e.message)  
end;

End;

但在 ADO 中,我尝试了不同的示例,但出现了不同的错误,例如 EOleError/EDatabaseError/...

我尝试了以下 2 点以在 ADO 中引发错误,但我遇到了不同的错误

1) 在 sql 服务器存储过程中,我在第一行引发了错误。当我在 delphi 中使用 TADOStoredProc 执行该过程时,我得到 EOleError.

2) 在 TADOQuery 中我写了一个错误的 sql 语句所以当我 open TADOQUery 我收到 EDatabaseError.

所以现在我很困惑如何处理 ADO 错误。 我不想检查每个表单中的所有错误(EOleError、EDatabaseError、EAdoError...) 所以我写了 2 个示例, 请建议我哪个好。如果两者都错了,请给我一个很好的例子。

示例 1:
这里我在示例中仅显示一种形式,因此 Delphi Procedure HandleErrorsfunction GetErrorDescription 可能看起来很愚蠢。我不想写同一篇文章 所有形式的代码。当涉及到真实场景时,我将在不同的单元上保留 Delphi Procedure HandleErrorsfunction GetErrorDescription 并在整个过程中使用该单元申请。

type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    Procedure HandleErrors(e: Exception );
    function GetErrorDescription : WideString;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.GetErrorDescription : WideString;
var
  LastErrorIndex : Integer;
begin
  LastErrorIndex  :=ADOConnection1.Errors.Count-1;
  Result:=ADOConnection1.Errors.Item[LastErrorIndex].Description;
  //Code            :=ADOConnection1.Errors.Item[LastErrorIndex].NativeError;
end;

procedure TForm1.HandleErrors(e: Exception);
var
  Code: Integer;
  ErrorDescription: WideString ;
begin
  if e is EOleError then
    ShowMessage(GetErrorDescription)
  else
  if e is EDatabaseError then
    ShowMessage(GetErrorDescription)
  else
  if e is EADOError then
    ShowMessage(GetErrorDescription)
  else
    ShowMessage(GetErrorDescription)
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
   // any database related operations
  except
    on E : Exception do
    begin
      HandleErrors(E);
    end;
  end;
end;

end.

示例 2:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ADODB, StdCtrls, DB,COMOBJ;

type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  LastErrorIndex : Integer;
begin
  try
   // any database related operations
  except
    on E : Exception do
    begin
      LastErrorIndex  :=ADOConnection1.Errors.Count-1;
      ShowMessage(ADOConnection1.Errors.Item[LastErrorIndex].Description);
    end;
  end;
end;

end.

哪个例子更好。能推荐个好的吗

正如我在评论中所说,您不应该将 AdoConnections 和数据集分散到多个表单中/相反,您应该将它们放在数据模块中,然后在表单的单元中使用数据模块的单元。这样,您将能够将表单上的 TDataSources 和 db-aware 组件连接到数据模块的数据集。

您可以做的另一件事是安装一个 application-wide 异常处理程序来集中您的异常处理,如果您想要这样做的话。 Delphi 的 Application 对象有一个 OnException 事件,您可以使用如下所示的代码将其分配给您自己的异常处理程序。

application-wide 异常处理程序的一个缺点是,在 OnException 处理程序中可能很难确定您的哪个对象实际上是导致异常的原因。

type
  TMainForm = class(TForm)
    [...]
    procedure FormCreate(Sender: TObject);
  private
    procedure ApplicationException(Sender: TObject; E: Exception);
  public
  end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Application.OnException := ApplicationException;
end;

procedure TMainForm.ApplicationException(Sender: TObject; E: Exception);
var
  AErrors : Errors;
  AError : Error;
  i : Integer;
  S : String;
begin
  Caption := 'Exception';
  if E is EDatabaseError then begin
    AErrors := DataModule1.AdoQuery1.Connection.Errors;
    for i := 0 to AErrors.Count - 1 do begin
      AError := AErrors.Item[i];
      S := Format('Number: %d, NativeError: %d, source: %s, description: %s',
        [AError.Number, AError.NativeError, AError.Source, AError.Description]);
      Memo1.Lines.Add(S);
    end;
  end;
end;