捕获 TClientDataSet.CommandText 中的错误
Posted
技术标签:
【中文标题】捕获 TClientDataSet.CommandText 中的错误【英文标题】:Trapping errors in TClientDataSet.CommandText 【发布时间】:2010-05-13 02:52:45 【问题描述】:我有一个 TClientDataSet 连接到一个 TDataSetProvider,而 TDataSetProvider 又连接到一个 TAdsQuery。我设置了 SQL 命令,然后像这样打开 ClientDataset:
try
CDS.CommandText := 'SELECT * FROM tablename WHERE fieldname = 1';
CDS.Open
except
// trap exception here - this never gets executed!
end;
但是,如果 CommandText 中的 SQL 语句失败(语法错误或其他),我会在 Advantage 代码中得到一个异常,但它永远不会在我自己的异常处理代码中被捕获。
我有什么方法可以捕获此错误并将其很好地报告给用户。或者有没有办法在执行 SQL 查询之前验证它的语法?
我正在使用 Delphi Pro 2009 和 Advantage Local Server 9。
【问题讨论】:
【参考方案1】:Advantage 包括一个EADSDatabaseError,它将提供有关引发的异常的更多信息。
try
CDS.CommandText := 'SELECT * FROM tablename WHERE fieldname = 1';
CDS.Open
except
on E: EDatabaseError do
begin
if ( E is EADSDatabaseError ) then
begin
ErrorString := (E as EADSDatabaseError).SQLErrorCode + E.Message;
application.messagebox ( pchar(ErrorString), 'Advantage Database Error', 0 )
end
else
application.messagebox (pchar(E.message), 'Native Database Error', 0 );
end;
end;
您可以使用 TAdsQuery 组件的VerifySQL 方法在执行 SQL 语句之前检查它的语法。如果 SQL 语法不正确,这将引发 EADSDatabaseError 异常。
【讨论】:
酷,我从来不知道 VerifySQL 方法。我开始怀疑我的代码中存在一些其他问题,这些问题正在破坏异常,但是能够在运行之前验证 SQL 总比事后捕获异常要好。【参考方案2】:当您从 IDE 中运行它时,或者当您直接从可执行文件运行时,您是否获得了异常代码(不是您想要的捕获的异常)?我问的原因是IDE会首先报告错误/异常,如果你不继续,你将永远看不到实际的异常陷阱。
可以针对某些错误类型关闭 IDE 捕获,尽管我一般不喜欢这样做。您可以通过在 Delphi IDE 之外自行运行应用程序来检查这是否是问题所在。
此外,您最初编写的代码应该防止所有错误浮出水面,这可能不是您想要的。同样的道理,如果你想让它看起来更好,你可以显示消息,如下所示,然后处理它。
try
CDS.CommandText := 'SELECT * FROM tablename WHERE fieldname = 1';
CDS.Open
except
on E: Exception do begin
ShowMessage(E.Message);
// optionally Exit, Abort or what else, to stop execution of the next statements
end;
end;
【讨论】:
【参考方案3】:我不清楚为什么要在 TClientDataSet 上设置命令文本。我相信如果你设置了 TAdsQuery.SQL 属性,然后打开 TClientDataSet,你会得到你正在寻找的行为。
当我设置它并运行您的代码时,我得到了异常“不允许更改 CommandText”。
procedure TForm57.Button1Click(Sender: TObject);
begin
try
CDS.CommandText := 'SELECT * FROM tablename WHERE fieldname = 1';
CDS.Open;
except
on E : Exception do
ShowMessage( 'got it:' + E.message );
end;
end;
【讨论】:
好点子,我不知道将 ClientDataset 的 CommandText 设置为与 AdsQuery 的 SQL 相反可能会有什么不同。我会调查的。也许当时我只是认为应用程序不必了解底层数据库会更好。我这样做是为了修改 ClientDataset 中的 CommandText,您必须打开 DataSetProvider 中的 poAllowCommandText 选项。如果您不这样做,则会收到“不允许更改 CommandText”错误。【参考方案4】:-
要执行 SQL 命令,您必须使用 TAdsQuery 而不是 TAdsTable。
奇怪的是,TAdsTable 没有返回错误。正如它应该说的“未知表”之类的东西。
捕获错误并将其报告给用户:
try
CDS.CommandText := 'SELECT * FROM tablename WHERE fieldname = 1';
CDS.Open
except
on E: Exception do begin
Application.HandleException(Self);
// optionally Exit, Abort or what else, to stop execution of the next statements
end;
end;
没有简单的方法来验证 SQL 查询的语法。因为,那么您将需要重现 DBMS 解析器行为,这是一项复杂的编程任务。更简单的是向 DBMS 提交命令,希望它是正确的(乐观的方法)。
【讨论】:
抱歉,我的意思是说 Provider 与 AdsQuery 相关联,而不是与 AdsTable 相关联。异常的形式应该不是问题。如果您想捕获每种类型的异常,则不必有“on Exception”子句。以上是关于捕获 TClientDataSet.CommandText 中的错误的主要内容,如果未能解决你的问题,请参考以下文章