国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Delphi > 正文

DELPHI的異常及事務(wù)保護的常見問題淺析

2019-11-18 18:29:42
字體:
供稿:網(wǎng)友
 1、Exit方法

  原以為Exit方法執(zhí)行后,會馬上退出過程,但是真正做了一個例子來測試后,才讓我改變了想法。請看下面這
個例子,flag最后被賦值為'C'。

================================================================================================
  var
    flag: string;
  begin
    try
      flag := 'A';

      Exit;

      flag := 'B';
    finally
      flag := 'C';
    end;

    flag := 'D';
  end;

================================================================================================
  分析:不論try子句如何結(jié)束,finally 子句總是被執(zhí)行。(多謝ylmg網(wǎng)友)

2、一個能讓整個系統(tǒng)停止運作的小問題

  在數(shù)據(jù)庫系統(tǒng)設(shè)計中,經(jīng)常使用事務(wù)操作來保證數(shù)據(jù)的完整性,但是設(shè)計不當(dāng),卻容易產(chǎn)生比較大的影響,下面舉個例子說明雖然數(shù)據(jù)完整性保證了,但是可能令到系統(tǒng)完全停止運作:
  ================================================================================================
  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本身,而是它將程序掛起,需要用戶干預(yù)后,才繼續(xù)執(zhí)行后面的操作;如果用戶這時候離開了計算機,或者沒有對這些對話框進行確定操作的話,可想而知,整個系統(tǒng)因為這個事務(wù)沒有結(jié)束而通通處于等待狀態(tài)了。

  為了避免這個問題,原則有兩個:
  (1)、事務(wù)啟動后,無需用戶干預(yù),程序可以自動結(jié)束事務(wù);
  (2)、在事務(wù)里面做時間最短的操作。


3、try...except...end結(jié)構(gòu)

  下面舉個例子來說明try結(jié)構(gòu),還是使用事務(wù)操作的例子:

  有問題的代碼:
    ================================================================================================
  try
    ...

    AdoConnection1.BeginTrans;

    ...

    AdoConnection1.CommitTrans;
  except
    AdoConnection1.RollbackTrans;
  end;
    ================================================================================================

  分析:如果try之后到AdoConnection1.BeginTrans這段代碼中出現(xiàn)異常,將跳轉(zhuǎn)到AdoConnection1.RollbackTrans執(zhí)行,但是AdoConnection1因為出錯并沒有啟動事務(wù),所以AdoConnection1.RollbackTrans執(zhí)行時出錯了。

  正確的代碼:  ================================================================================================
  AdoConnection1.BeginTrans;
  try
    ...

    ...

    AdoConnection1.CommitTrans;
  except
    AdoConnection1.RollbackTrans;
  end;
    ================================================================================================

  總之,try的架構(gòu)是用來保護異常的操作的,try...except之間的產(chǎn)生異常都會執(zhí)行except...end之間的操作,設(shè)計try命令時一定要注意架構(gòu)的合理性。

4、欺騙了自己的事務(wù)保護

  在做數(shù)據(jù)庫應(yīng)用軟件時,我們經(jīng)常需要碰到下面的問題:對原有數(shù)據(jù)進行判斷,然后做出相應(yīng)的修改。這個問題看似比較簡單,但是如果考慮到網(wǎng)絡(luò)上還有別的人在使用同一個系統(tǒng),那么,你就不的不考慮可能被意外改變的問題了。我的同事比較粗心,雖然在我的提示下考慮了多用戶問題,但是他還是寫下了有問題的代碼:
    ================================================================================================
  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之前判斷數(shù)據(jù),然后使用AdoConnection1.Execute改變數(shù)據(jù),如果這個數(shù)據(jù)是共享的,那么在判斷之后到AdoConnection1.BeginTrans之前的這段時間里頭,tb1的數(shù)據(jù)可能已經(jīng)發(fā)生了改變,這個事務(wù)保護是沒有用處的。

  正確的方法是判斷和修改必須是同一份數(shù)據(jù),下面示例了有兩個方法(區(qū)別在于啟動事務(wù)的位置不相同):
 
  代碼1(使用事務(wù)保護以后,判斷的和修改的是同一數(shù)據(jù)):
  ================================================================================================
  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(使用異常捕捉,假如判斷和修改的不是同一份數(shù)據(jù),adsTemp.Post時會出現(xiàn)異常,這個是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;


上一篇:回調(diào)函數(shù)與Delphi的事件模型

下一篇:淺談控件(組件)制作方法一(附帶一delphi導(dǎo)出數(shù)據(jù)到Excel的組件實例)(原創(chuàng))

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 常德市| 出国| 搜索| 吉木乃县| 六盘水市| 自治县| 长乐市| 潼南县| 射洪县| 驻马店市| 新兴县| 临夏市| 阿尔山市| 资中县| 宜宾市| 汉川市| 丽水市| 施甸县| 彰武县| 抚松县| 宜兰市| 鄂尔多斯市| 湖南省| 舞阳县| 垫江县| 贡山| 兰溪市| 明溪县| 巫溪县| 邳州市| 岚皋县| 沅陵县| 宜阳县| 宝应县| 九龙城区| 仲巴县| 小金县| 石嘴山市| 普安县| 嘉善县| 饶平县|