转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
DELPHI的异常及事务保护的常见问题浅析         ★★★★

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

作者:闵涛 文章来源:闵涛的学习笔记 点击数:654 更新时间:2009/4/23 18:36:55

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;
    ================================================================================================


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台