gpt4 book ai didi

delphi - 为什么OnEditError或OnPostError不能在TClientDataSet中捕获无效的用户条目?

转载 作者:行者123 更新时间:2023-12-03 15:23:46 25 4
gpt4 key购买 nike

我有一个通过一些数据源附加到TDBGrid的内存数据集。问题是,只要用户在数字字段中输入减号并按ENTER或导航到另一条记录,就会触发AV(验证错误)。我无法从TDBGrid或TClientDataSet(OnEditError,OnPostError)中捕获AV。

我在这里做错什么了吗?如果没有,是否有人可以解决此问题?

使用Delphi XE2 Enterprise,第4次更新;最新的MIDAS.DLL;目标平台:Win64。

================================================== ===========================

请尝试以下操作:

1-创建一个新的VCL应用程序/窗体,并将对象:TClientDataSet,TDBGrid和TDataSource添加到窗体。 ClientDataSet未附加到任何数据库(内存中)

2-将持久性数字字段添加到表1(TClientDataSet)。

3-链接以上三个对象。持久字段的列应显示在TDBGrid上。

4-在主窗体的OnShow方法中添加以下行:

Table1.Active:= False;

Table1.CreateDataSet;

Table1.Active:= True;

5-运行程序,然后在数字字段列中键入减号,然后按Enter。

检查AV,然后尝试将OnEditError和/或OnPostError事件处理程序添加到Table1中以捕获AV。您不能中止该帖子。意思是,AV将会发生,您只能使用Application.OnException处理程序来捕获它。不好假设您的应用程序包含许多形式和例程,而不是更高级别,则应该能够在程序运行的级别上执行某些操作。

我希望我的问题更加清楚。

最佳答案

正如Ken所说,没有示例代码很难帮助您。因此,我将无法直接回答您的问题,但是通过一些提示,您可能可以自己解决问题。因此,我将尝试教您钓鱼。 ;)

我确实在Delphi 3和6中对TClientDataSet有一定的经验。我怀疑事情是否已经改变了很多。另外,我将更加专注于技巧,以正确的方向启动您。

首先,请确保使用Debug DCU进行编译,以便可以在VCL代码中获得断点。不要害怕阅读并逐步阅读这些代码-这是一种学习的好方法。另外,您还可以看到Borland / CodeGear / Embarcadero的所有丑陋错误。

我假设您已经启用了“异常停止”功能(因此,为什么您知道自己特别遇到了AV错误)。

做你的测试。当您获得AV时,您可能会出现在DbClient.pas(或者可能是较低级别的单元之一)中。

遍历调用堆栈,寻找在try..except块的try部分内的位置,该块会吞下Exception或将其短路到另一个处理程序,然后吞下它。

注意:DbClient.pas充满了以下错误代码的很多实例:

except //swallowing or squashing exceptions is 
end; //very dangerous and should be avoided.

except
//short-circuiting to Application.HandleException (usually informs the user)
//but is not much better. The point is the rest of the program up the
//call-stack remains blissfully unaware that something went wrong.
Application.HandleException(Self);
Action := raAbort;
end;



  旁注:仅仅因为Borland做到了,并不意味着这是一个好习惯。您和许多其他人已经并且将为此感到沮丧。


一旦找到,就到了一半。现在您知道了为什么没有收到AV的通知。
现在,在构成该调用栈一部分的代码中的某个地方,将提示您如何处理该错误。您还可以在VCL代码中更早地放置一个断点,以便您逐步执行来查看导致Exception的事件序列。由于您特别提到了AV(访问冲突),因此请查找引用nil的对象。

D5 DbClient.pas的以下片段是导致问题的一个示例。

    FOnReconcileError(DataSet, E, UpdateKind, Action);
finally
E.Free;
end;
except
Application.HandleException(Self);
Action := raAbort;
end;


从上面可以看到,某些情况需要您实现OnReconcileError事件处理程序。没有它,该dll将不会被回调到上述代码片段中,并且许多错误被悄悄地掩盖起来,使您抓狂。

我对TClientDataSet的经验是,要“正确”使用它,还需要做一些其他的事情。这在文档中不是特别明显。尽管一旦您弄清了所有应该做的零散的事情,如何做这些事的示例就会好一些。

不幸的是,我对所有这些东西的记忆有些模糊。因此,这是一个非常粗糙的指南,可能会遗漏很多。


考虑使用OnReconcileError事件处理程序。
考虑实现UpdateProvider对象。
您提到将其用作内存数据集,因此您可能正确使用了CreateDataSet。但是,如果我没记错的话,您可以使用2个选项来指定字段,并且一些更详细的属性有些挑剔。
不相关的提示:小心字符串字段的长度,TClientDataSet曾经(并且可能仍然)以类似于短字符串的方式来成群存储。


编辑

根据问题中的其他信息并使用上述技术,您将从以下方法中抛出EDatabaseError。

procedure TIntegerField.SetAsString(const Value: string);
var
E: Integer;
L: Longint;
begin
if Value = '' then Clear else
begin
Val(Value, L, E);
if E <> 0 then DatabaseErrorFmt(SInvalidIntegerValue, [Value, DisplayName]);
SetAsInteger(L);
end;
end;


在调用堆栈的较高位置,您将获得以下方法,以提示如何解决问题。

procedure TField.SetEditText(const Value: string);
begin
if Assigned(FOnSetText) then FOnSetText(Self, Value) else SetText(Value);
end;


另外,如果您一直遵循调用堆栈直到KeyPress,您将注意到根本不涉及数据集或网格代码。

您尝试处理OnPost错误中的错误之所以不起作用,是因为您没有尝试发布记录的机会。您会收到“字段验证”错误,并且该字段上的内容也需要处理。

回到暗示如何解决错误的提示-您将必须为该字段实现OnSetText事件。

但是我建议不要这样做。开箱即用的行为是完全可以接受的!用户收到一条错误消息,说明他们做错了什么,他们有机会进行修复并再次尝试。如果他们改变主意,则可以点击Escape并取消编辑。

关于delphi - 为什么OnEditError或OnPostError不能在TClientDataSet中捕获无效的用户条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10917671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com