分享
 
 
 

DELPHI的异常及事务保护的常见问题浅析

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

1、Exit方法

原以为Exit方法执行后,会马上退出过程,但是真正做了一个例子来测试后,才让我改变了想法。请看下面这

个例子,flag最后被赋值为'C'。

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

var

flag: string;

begin

try

flag := 'A';

Exit;

flag := 'B';

finally

flag := 'C';

end;

flag := 'D';

end;

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

分析:不论try子句如何结束,finally 子句总是被执行。(多谢ylmg网友)

2、一个能让整个系统停止运作的小问题

在数据库系统设计中,经常使用事务操作来保证数据的完整性,但是设计不当,却容易产生比较大的影响,下面举个例子说明虽然数据完整性保证了,但是可能令到系统完全停止运作:

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

AdoConnection1.BeginTrans;

try

...

if Application.MessageBox('是否确定删除?', '询问', MB_YESNO+MB_ICONQUESTION)<>IDYes then //(1)

begin

...

end;

Application.MessageBox('操作失败', '警告', MB_OK); //(2)

AdoConnection1.CommitTrans;

except

Application.MessageBox('操作失败', '警告', MB_OK); //(3)

AdoConnection1.RollbackTrans;

end;

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

分析:上面代码中的问题都是由于(1)、(2)、(3)的Application.MessageBox引起,但是引起问题的并不是Application.MessageBox本身,而是它将程序挂起,需要用户干预后,才继续执行后面的操作;如果用户这时候离开了计算机,或者没有对这些对话框进行确定操作的话,可想而知,整个系统因为这个事务没有结束而通通处于等待状态了。

为了避免这个问题,原则有两个:

(1)、事务启动后,无需用户干预,程序可以自动结束事务;

(2)、在事务里面做时间最短的操作。

3、try...except...end结构

下面举个例子来说明try结构,还是使用事务操作的例子:

有问题的代码:

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

try

...

AdoConnection1.BeginTrans;

...

AdoConnection1.CommitTrans;

except

AdoConnection1.RollbackTrans;

end;

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

分析:如果try之后到AdoConnection1.BeginTrans这段代码中出现异常,将跳转到AdoConnection1.RollbackTrans执行,但是AdoConnection1因为出错并没有启动事务,所以AdoConnection1.RollbackTrans执行时出错了。

正确的代码: ================================================================================================

AdoConnection1.BeginTrans;

try

...

...

AdoConnection1.CommitTrans;

except

AdoConnection1.RollbackTrans;

end;

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

总之,try的架构是用来保护异常的操作的,try...except之间的产生异常都会执行except...end之间的操作,设计try命令时一定要注意架构的合理性。

4、欺骗了自己的事务保护

在做数据库应用软件时,我们经常需要碰到下面的问题:对原有数据进行判断,然后做出相应的修改。这个问题看似比较简单,但是如果考虑到网络上还有别的人在使用同一个系统,那么,你就不的不考虑可能被意外改变的问题了。我的同事比较粗心,虽然在我的提示下考虑了多用户问题,但是他还是写下了有问题的代码:

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

var

adsTemp: TAdoDataSet;

isOk: boolean;

begin

adsTemp := TAdoDataSet.Create(self);

try

adsTemp.Connection := AdoConnection1;

adsTemp.CommandText := 'select fid, fnumber from tb1 where fid=120';

adsTemp.Open;

isOk := adsTemp.FieldByName('fnumber').AsInteger>100;

finally

adsTemp.Free;

end;

if not isOk then

Exit;

AdoConnection1.BeginTrans;

try

AdoConnection1.Execute('update tb1 set ffull=ffull + 1 from tb1 where fid=120';

...

...

AdoConnection1.CommitTrans;

except

AdoConnection1.RollbackTrans;

end;

end;

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

分析:不知大家看出问题来了没有,在AdoConnection1.BeginTrans之前判断数据,然后使用AdoConnection1.Execute改变数据,如果这个数据是共享的,那么在判断之后到AdoConnection1.BeginTrans之前的这段时间里头,tb1的数据可能已经发生了改变,这个事务保护是没有用处的。

正确的方法是判断和修改必须是同一份数据,下面示例了有两个方法(区别在于启动事务的位置不相同):

代码1(使用事务保护以后,判断的和修改的是同一数据):

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

var

adsTemp: TAdoDataSet;

isOk: boolean;

begin

AdoConnection1.BeginTrans;

try

adsTemp := TAdoDataSet.Create(self);

try

adsTemp.Connection := AdoConnection1;

adsTemp.CommandText := 'select fid, fnumber, ffull from tb1 where fid=120';

adsTemp.Open;

if adsTemp.FieldByName('fnumber').AsInteger>100 then

begin

adsTemp.Edit;

adsTemp.FieldByName('ffull').AsInteger := adsTemp.FieldByName('ffull').AsInteger + 1;

adsTemp.Post;

end;

finally

adsTemp.Free;

end;

AdoConnection1.CommitTrans;

except

AdoConnection1.RollbackTrans;

end;

end;

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

代码2(使用异常捕捉,假如判断和修改的不是同一份数据,adsTemp.Post时会出现异常,这个是ADODataSet对象具有的特性):

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

var

adsTemp: TAdoDataSet;

isOk: boolean;

begin

adsTemp := TAdoDataSet.Create(self);

try

adsTemp.Connection := AdoConnection1;

adsTemp.CommandText := 'select fid, fnumber, ffull from tb1 where fid=120';

adsTemp.Open;

if adsTemp.FieldByName('fnumber').AsInteger>100 then

begin

AdoConnection1.BeginTrans;

try

adsTemp.Edit;

adsTemp.FieldByName('ffull').AsInteger := adsTemp.FieldByName('ffull').AsInteger + 1;

adsTemp.Post;

AdoConnection1.CommitTrans;

except

AdoConnection1.RollbackTrans;

end;

end;

finally

adsTemp.Free;

end;

end;

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有