怎样捕获数据库异常?(20分)

  • 主题发起人 李汉涛
  • 开始时间

李汉涛

Unregistered / Unconfirmed
GUEST, unregistred user!
有一DBEdit控件,对应数据库
一Field(Short Int类型),
若输入的数据超出范围,
就会产生一个异常,
请问怎样捕获此异常,
并产生自己定义的异常?
 
这个异常不用捕获.
一般是你自己控制输入的范围.
若是你自己想集中处理遗产,可以
type MyException = class(Exception);
再重载Application.OnException,自己处理;

type TForm1 = class(TForm)
...
procedure myExceptionProcess(Sender: TObject;
E: Exception) of object;
end;

Tform1create:

oldExceptionProcess:=application.Onexception;
application.Onexception:=myExceptionprocess;

myExceptionProcess:
begin
if E is MyException then
application.messagebox('haha','I Captured it!',1);
oldExceptionProcess;
end;

这只是自己处理异常的一种方法,可以有多种方法,比如try...except.
try

except
on myException do
...
end;

1(建议).对于这个Field,例如是 SomeTable.AField,
在AField.onValidate中可以
if Afield.asinteger >... then
begin
raise myException.create(..); // 显示出错
abort;
end;

2. 在DbEdit.onExit中进行同样的检查.

 
实际上不用自己定义异常,在DBEDIT的ONVAILD(也许拼写有错,当离开控件)加入以下代码:
try
strtoint(dbedit1.text);
except
showmessage('...');
dbedit1.setfocus //重新输入
end;
 
不好意水,是OnExit,我昏头了!
 
CJ:
如果我没有离开DBEDit,而是直接
按DBNavigator的Post按钮,如何捕获
此异常呢?

 
我已经在上面回答了呀,用TField.onValidate!
看最后那部分.

dbedit.onExit我也提到了,但是不建议用.
从逻辑层次上来说还是Tfield.onValidate好.因为如果要求
换用别的控件,比如dbGrid,就要再写一次,不如在字段上直
接控制好.

还可以用Table.BeforePost;Table.BeforeInsert;但是由于同
样的原因(逻辑层次),不建议用于字段一级的操作.

(如果找不到这个控件,在table上右点,打开Field编辑窗口,
在其上右点,Add all Fields,再在某个Field上点选,左侧
Object Inspector上可以找到TField.OnValidate.)
 
我试过在各种事件里添加代码,
可是EDatabaseError还是照常
不误地产生,不信你们可以试试看。
 
AField.OnValidate:
if Afield.asinteger >32767 then
abort;

你用这段代码,肯定不会出问题.我为了回答这个问题,特地编了一个例子.
正常的才会Post给你. 况且作了很多数据库程序了,都是这么做的.

如果再出错误,可能是其他地方有问题.
 
实在不幸(应该不会)可以捕获程序异常,写自己的错误处理程序!没有记清楚,
可能是这样的:
MyOnerror := application.onerror
但是曹兄说的有道理,因该可以解决.
为什么用DBNAVIGATOR!你会发现有很多限制!
推荐在有数据输入的FORM中使用自己写的数据库导航!
 
给一个例子给你,就是我做实验的:

PAS:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, Grids, DBGrids, StdCtrls, Mask, DBCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
DBEdit1: TDBEdit;
DBNavigator1: TDBNavigator;
DBGrid1: TDBGrid;
Table1Aa: TIntegerField;
procedure Table1AaValidate(Sender: TField);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Table1AaValidate(Sender: TField);
begin
if table1aa.asinteger >15 then
begin
application.messagebox('Error','',1);
abort;
end;
end;

end.


DFM:
object Form1: TForm1
Left = 200
Top = 104
Width = 696
Height = 480
Caption = 'Form1'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
PixelsPerInch = 96
TextHeight = 13
object DBEdit1: TDBEdit
Left = 296
Top = 88
Width = 121
Height = 21
DataField = 'Aa'
DataSource = DataSource1
TabOrder = 0
end
object DBNavigator1: TDBNavigator
Left = 128
Top = 192
Width = 240
Height = 25
DataSource = DataSource1
TabOrder = 1
end
object DBGrid1: TDBGrid
Left = 152
Top = 264
Width = 233
Height = 129
DataSource = DataSource1
TabOrder = 2
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object Table1: TTable
Active = True
DatabaseName = 'test'
TableName = 'aa.db'
Left = 184
Top = 80
object Table1Aa: TIntegerField
FieldName = 'Aa'
OnChange = Table1AaValidate
end
end
object DataSource1: TDataSource
DataSet = Table1
Left = 208
Top = 88
end
end
 
对于这个问题,我诚恳地向各位道歉.

我没有看清楚题目,事实上,这个错误已经不是TField.Onvalidata所能捕获的了.
早在TField.SetText时,此错误就已经发生. 所以正确的方法是:

procedure TForm1.Table1AaSetText(Sender: TField; const Text: String);
begin
if ( length(text)>length('65535') ) or
( text> format('0.5d',[65535]) ) then application.messagebox('超界','',1);
end;

另外,由于同样的原因,DBEdit.OnExit也不能捕获.

另一个方法就是重载application.OnException了,但是只返回一个
泛泛的EDataSetError,出了错也不好分别.

procedure tform1.myException(Sender: TObject; E: Exception);
begin
application.messagebox('OH!','',1);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
application.OnException:=myException;
end;


再次向李汉涛表示歉意.
 
刚才那个没做过测试,看这个:
procedure TForm1.Table1AaSetText(Sender: TField; const Text: String);
var code:integer; v:integer;
begin
val(text,v,code);
if code<>0 then application.messagebox('超界','',1)
else table1aa.AsInteger:=v;
end;
 
谢谢曹晓钢,问题已经解决了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
I
回复
0
查看
523
import
I
顶部