本主题描述了如何用FireDAC处理数据库错误。

一、概述
EFDDBEngineException类是所有DBMS异常的基类。单个异常对象是一个数据库错误的集合,可以通过EFDDBEngineException.Errors[]属性访问,并由TFDDBError类表示。
FireDAC结合了 "个性化 "和EFDDBEngineException异常和TFDDBError错误类的统一。"个性化 "意味着一个驱动程序可以有自己的异常和错误类,其中包含DBMS的特定信息。
DBMS | Exception class | Error class |
Advantage Database | ||
DataSnap server | ||
dbExpress v4 | ||
Firebird | ||
IBM DB2 | ||
Informix | ||
InterBase | ||
Microsoft Access | ||
Microsoft SQL Server | ||
MySQL | ||
ODBC | ||
Oracle | ||
PostgreSQL | ||
SQLite | ||
Sybase SQL Anywhere | ||
Teradata Database |
TFDDBError有一个ErrorCode属性,它是本地DBMS的错误代码。
"统一 (Unification)"意味着所有的驱动程序异常类都继承自EFDDBEngineException--一个单一的基类,包含独立于驱动程序的信息。它的Kind属性是一个独立于DBMS的错误代码。例如,处理唯一键违例的代码可能如下:
try
FDQuery1.ExecSQL('insert into MyTab(code, name) values (:code, :name)', [100, 'Tokyo']);
except
on E: EFDDBEngineException do begin
if E.Kind = ekUKViolated then
ShowMessage('Please enter unique value !');
raise;
end;
end;
二、错误信息
-
错误信息主要由EFDDBEngineException属性呈现。
-
Errors -- TFDDBError对象的集合。
-
ErrorCount -- Errors集合中的错误数量。
-
Kind -- 独立于DBMS的错误种类。
-
Message -- 实际的错误信息。
-
并由TFDDBError属性。
-
ErrorCode -- DBMS供应商特定的错误代码。
-
Kind -- DBMS独立的错误种类。
-
Message -- 错误信息。
为了简化应用程序的调试或使异常记录的信息量更大,EFDDBEngineException提供了SQL和Params属性。
另外,根据错误区域和DBMS提供高级错误信息的能力,以下的TFDDBError属性是有用的。
-
当涉及到SQL解析错误时,CommandTextOffset返回SQL命令文本中的偏移。
-
当涉及到违反约束条件、DB对象更改失败或其他一些错误时,ObjName属性会返回一个数据库对象的名称。
-
当涉及到一个数组DML错误时,那么RowIndex返回错误所属的数组行索引。
三、处理异常情况
-
异常可以通过以下方式之一进行处理。
-
使用try/except/end结构。这是一种标准的Delphi处理异常的方式。比如说:
FDConnection1.StartsTransaction;
try
FDQuery1.ExecSQL;
FDConnection1.Commit;
except
on E: EFDDBEngineException do begin
FDConnection1.Rollback;
// do something here
raise;
end;
end;
-
设置TFDQuery.OnError事件处理程序。
-
设置TFDConnection.OnError事件处理程序。这些都是处理异常记录或异常 "调整 "的好方法。比如说:
procedure TForm1.FDConnection1Error(ASender: TObject; const AInitiator: IFDStanObject;
var AException: Exception);
var
oExc: EFDDBEngineException;
begin
if AException is EFDDBEngineException then begin
oExc := EFDDBEngineException(AException);
if oExc.Kind = ekRecordLocked then
oExc.Message := 'Please, try the operation later. At moment, the record is busy'
else if (oExc.Kind = ekUKViolated) and SameText(oExc[0].ObjName, 'UniqueKey_Orders') then
oExc.Message := 'Please, provide the unique order information. It seems, your order was already put';
end;
end;
FDConnection1.OnError := FDConnection1Error;
-
设置TFDQuery.OnExecuteError事件处理程序,用于处理Array DML的具体错误。
-
设置TFDQuery.OnUpdateError事件处理程序,用于处理更新发布的错误。
-
设置TFDConnection.OnLost, OnRestored, OnRecover事件处理程序,用于处理连接丢失的错误。
四、使用终端用户错误对话框
在TFDGUIxErrorDialog组件的帮助下,终端用户可以得到关于数据库返回错误的通知。

要使用该对话框,只需将该组件放在表单的某个地方。对话框钩住TApplication.OnException事件处理程序,当有一个未处理的FireDAC异常时,就会弹出对话框。在 "查询 "页面,你可以看到由异常产生的SQL命令文本。在对话框中按下Ctrl+C可以将完整的异常信息放入剪贴板。