人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當(dāng)前位置:蘿卜系統(tǒng)下載站 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

用Delphi模擬組件的2階段提交

用Delphi模擬組件的2階段提交

更新時(shí)間:2022-09-02 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

問題提出:寫了一個(gè)數(shù)據(jù)庫(kù)操作的類TDBOperate_DL,統(tǒng)一對(duì)數(shù)據(jù)庫(kù)的操作嘛。提供了聲明事務(wù)開始、提交事務(wù)和回滾事務(wù)的方法供其他類調(diào)用。

TDBOperate_DL = class

  private

    ADOC:TADOConnection;

    ADOQ:TADOQuery;

    isDestroyADOC:Boolean;    //是否銷毀自己的ADOC?

    fIsInTrans:Boolean;        //是否已經(jīng)開始事務(wù)

  public

    isCommit:Boolean;         //是否要提交事務(wù),缺省是真,如果有類投票說反對(duì)提交,就為假

    function IsInTrans:Boolean;

    constructor Create(const newADOC:TADOConnection);overload;

    constructor Create(const ServerName,DataBaseName,UserID,Password:String);overload;

    destructor Destroy;override;

    procedure BeginTrans;

    procedure CommitTrans;

    procedure RollbackTrans;

    procedure Execute(const sqlString:String);

    function GetDataset(const sqlString:String):_Recordset;

    function GetConnection:TADOConnection;

    procedure SetConnection(const newADOC:TADOConnection);

  end;

       一些函數(shù)的實(shí)現(xiàn):

procedure TDBOperate_DL.BeginTrans;          //開始事務(wù)

begin

  self.ADOC.BeginTrans;

  self.fIsInTrans := true;

end;



procedure TDBOperate_DL.CommitTrans;              //提交事務(wù)

begin

  self.ADOC.CommitTrans;

  self.fIsInTrans := false;

end;



procedure TDBOperate_DL.RollbackTrans;              //回滾事務(wù)

begin

  self.ADOC.RollbackTrans;

  self.fIsInTrans := false;

end;



function TDBOperate_DL.IsInTrans: Boolean;         //查看事務(wù)是否已開始

begin

  result := self.fIsInTrans;

end;



寫了一個(gè)TThing類,用于向數(shù)據(jù)庫(kù)中添加、修改或刪除有關(guān)某種東西的記錄,調(diào)用TDBOperate_DL類完成。為了調(diào)用方便,因此有關(guān)的事務(wù)就放在了TThing類中,外部調(diào)用時(shí)不用考慮事務(wù)了。

如:

procedure Tthing.Drop(const thing:String);

var

  sqlString:String;

begin

  sqlString := 刪除的SQL語句;

  self.DBOperate.BeginTrans;           // DBOperate是TDBOperate_DL類型的私有變量,創(chuàng)建Tthing類實(shí)例時(shí)傳入的參數(shù)。

  try

    self.DBOperate.Execute(sqlString);

    self.DBOperate.CommitTrans;

  except

    self. DBOperate.RollbackTrans;

    raise;

  end;

end;

后來又寫了個(gè)TPerson類,用于向數(shù)據(jù)庫(kù)中添加、修改或刪除有關(guān)人的記錄。同樣事務(wù)放在了TPerson類中,現(xiàn)在我想刪除人的記錄時(shí)順便調(diào)用TThing類刪除和人有關(guān)的東西,事務(wù)問題就出現(xiàn)啦:事務(wù)不能嵌套啊。如果先刪除TThing,再重新聲明事務(wù)刪除TPerson,如果TPerson出錯(cuò),還怎么回滾TThing?

如:

procedure Tperson.Drop(const person:String);

var

  sqlString:String;

  thing:Tthing;

begin

  sqlString := 刪除的SQL語句;

  thing := Tthing.Create(self.DBOperate);              //TDBOperate_DL類型的DBOperate是作為參數(shù)傳進(jìn)去的。

  Self.DBOperate.BeginTrans;

  Try

    Thing.Drop(person);               //里面有事務(wù)見上面的代碼

    Self.DBOperate.Execute(sqlString);

    self.DBOperate.CommitTrans;

  except

    self.DBOperate.RollbackTrans;

    raise;

  end;

end;

解決方法,兩階段提交,先粘點(diǎn)背景知識(shí):

不論兩層或三層體系,事物處理都是通過兩階段提交實(shí)現(xiàn)的。在第一階段,每個(gè)執(zhí)行的的資源\記錄被寫入 事物環(huán)境(Transcation Context)中,然后資源協(xié)調(diào)者順序查詢每一個(gè)參與事物的執(zhí)行是否成功,如果都沒有問題的話,就進(jìn)入第二階段,每個(gè)執(zhí)行都開始Commit它的操作。如果有一個(gè)執(zhí)行有問題的話,資源協(xié)調(diào)者通知所有下屬的執(zhí)行放棄Commit,恢復(fù)數(shù)據(jù)原狀態(tài)。

參考COM+的事務(wù)運(yùn)行,如果一個(gè)組件是需要事務(wù)的,那么在組件創(chuàng)建時(shí),事務(wù)就已經(jīng)開始了,在組件銷毀時(shí)進(jìn)行事務(wù)投票,如果是根事務(wù),則進(jìn)行提交或回滾事務(wù)。(如果組件支持池化,這兩種情況發(fā)生在組件激活和休眠事件中)。于是我們定義一個(gè)類如下。

//業(yè)務(wù)類的祖先類,用于提供統(tǒng)一的事務(wù)支持

  TTS_DL = class

  private

    isRootTrans:Boolean;      //是否是根事務(wù)

    isNeedTrans:Boolean;      //是否需要事務(wù)

  public

    DBOperate:TDBOperate_DL;   //操作數(shù)據(jù)庫(kù)的類的實(shí)例

    procedure SetComplete;

    procedure SetAbort;

    constructor Create(const newDBOperate:TDBOperate_DL;needTrans:Boolean);//是否需要事務(wù)支持

    destructor Destroy;override;

  end;

在該類創(chuàng)建時(shí),除了傳遞進(jìn)操作數(shù)據(jù)庫(kù)的類的實(shí)例外,再傳入一個(gè)是否需要事務(wù)的標(biāo)志,因?yàn)槿绻侵蛔鲎x取數(shù)據(jù)庫(kù)的操作,就用不著事務(wù)了。

類實(shí)現(xiàn)代碼如下:

constructor TTS_DL.Create(const newDBOperate: TDBOperate_DL;

  needTrans: Boolean);

begin

  inherited Create;

  self.DBOperate := newDBOperate;              

  self.isNeedTrans := needTrans;                     //賦值是否需要事務(wù)

  if self.isNeedTrans then

  begin

    //如果在事務(wù)里,就不是根事務(wù),保留事務(wù)上下文里isCommit的值不變

    if self.DBOperate.isInTrans then

      self.isRootTrans := false

    else

    begin

      self.DBOperate.BeginTrans;           //是根事務(wù),就開始事務(wù)

      self.isRootTrans := true;

      self.DBOperate.isCommit := true;       //初始化提交標(biāo)志為要提交事務(wù)

    end;

  end;

end;



destructor TTS_DL.Destroy;

begin

  if self.isNeedTrans then

  begin

    //如果是根事務(wù),就按照投票結(jié)果進(jìn)行事務(wù)提交或回滾

    if self.isRootTrans then

    begin

      if self.DBOperate.isCommit then

        self.DBOperate.CommitTrans

      else

        self.DBOperate.RollbackTrans;

    end;

  end;

  inherited;

end;



procedure TTS_DL.SetAbort;

begin

  self.DBOperate.isCommit := self.DBOperate.isCommit And false;       //投票說要回滾

end;



procedure TTS_DL.SetComplete;

begin

  self.DBOperate.isCommit := self.DBOperate.isCommit And true; //投票說要提交

end;



回到剛才的業(yè)務(wù)類Tthing和Tperson,這次都從TTS_DL類繼承下來。

       Tthing = class(TTS_DL);

       Tperson = class(TTS_DL);

Tthing的刪除代碼該為如下:

procedure Tthing.Drop(const thing:String);

var

  sqlString:String;

begin

  sqlString := 刪除的SQL語句;

  try

    self. DBOperate.Execute(sqlString);

    self. DBOperate.SetComplete;         //投票提交

  except

    self. DBOperate.SetAbort;                     //投票回滾

    raise;

  end;

end;

Tperson的刪除代碼如下:

procedure Tperson.Drop(const person:String);

var

  sqlString:String;

  thing:Tthing;

begin

  sqlString := 刪除的SQL語句;

  thing := Tthing.Create(self. DBOperate,true);              //TDBOperate_DL類型的DBOperate是作為參數(shù)傳進(jìn)去的,true代表需要事務(wù)。

  Try

    Try

      Thing.Drop(person);

      Self.DBOperate.Execute(sqlString);

      self.DBOperate.SetComplete;           //投票提交

    except

      self. DBOperate.SetAbort;                       //投票回滾

      raise;

    end;

  finally

    thing.free;                                                           //記著一定要釋放

  end;

end;

記著保持程序中使用唯一的操作數(shù)據(jù)庫(kù)類TDBOperate_DL的實(shí)例,記著釋放業(yè)務(wù)類實(shí)例,如果是需要事務(wù)的,盡量早釋放,OK,搞定。

第一個(gè)版本,水平有限,還需要在實(shí)際應(yīng)用中完善,全當(dāng)拋磚引玉,請(qǐng)有經(jīng)驗(yàn)的大俠們拍磚吧:)

溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

本類教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 襄垣县| 西青区| 双峰县| 资源县| 邵阳县| 田东县| 罗山县| 临武县| 宜昌市| 尚志市| 柳林县| 罗城| 颍上县| 门头沟区| 香格里拉县| 沽源县| 东兴市| 丹寨县| 平江县| 桂平市| 潼关县| 上虞市| 五指山市| 威宁| 沁阳市| 玛沁县| 隆尧县| 磐安县| 丹江口市| 蓬溪县| 玉林市| 卢氏县| 莱州市| 南漳县| 满洲里市| 剑川县| 成都市| 马关县| 江永县| 体育| 台东县|