質問: データベース上の操作を統合するために、データベース操作クラス TDBPerate_DL を作成しました。トランザクションの開始を宣言し、トランザクションをコミットし、トランザクションをロールバックするためのメソッドが、他のクラスが呼び出すために提供されます。 TDBOperate_DL = class PRivate ADOC:TADOConnection; ADOQ:TADOQuery; isDestroyADOC:Boolean; // 独自の ADOC を破棄しますか? fIsInTrans:Boolean; //トランザクションが開始されたかどうか public isCommit:Boolean //トランザクションをコミットするかどうか、デフォルトは true、クラスが送信に反対する場合は false function IsInTrans:Boolean; TADOConnection );オーバーロード コンストラクター Create(const ServerName,DataBaseName,PassWord:String);オーバーロード Destroy;プロシージャ BeginTrans; CommitTrans; プロシージャ RollbackTrans; プロシージャ Execute(const sqlString:String):_Recordset; プロシージャ SetConnection(const newADOC:TADOConnection); ; // トランザクションを開始します self.ADOC.BeginTrans; self.fIsInTrans := true;end;procedure TDBOperate_DL.CommitTrans; //コミット トランザクションの開始 self.ADOC.CommitTrans; self.fIsInTrans := false;end;procedure TDBOperate_DL.RollbackTrans; //ロールバック トランザクションの開始 self.ADOC.RollbackTrans ; self.fIsInTrans := false;end;関数 TDBPerate_DL.IsInTrans: ブール値; //トランザクションが開始されたかどうかを確認します begin result := self.fIsInTrans;end;何かに関するレコードをデータベースに追加、変更、または削除する TThing クラスを作成し、TDBPerate_DL クラスを呼び出して完了します。呼び出しの便宜のために、関連するトランザクションは TThing クラスに配置されており、外部呼び出しを行うときにトランザクションを考慮する必要はありません。例:procedure Tthing.Drop(const thing:String);var sqlString:String;begin sqlString := selected SQL state; self.DBPerate.BeginTrans; // DBOperate は Tthing の作成時に渡される TDBPerate_DL 型のプライベート変数です。クラスインスタンスのパラメータ。 try self.DBOperate.Execute(sqlString); self.DBOperate.CommitTrans; self.DBOperate.RollbackTrans; end;end; その後、データベース Record 内の人物に関する情報を追加、変更、または削除するための Tperson クラスを作成しました。同じトランザクションが TPersonal クラスに配置されているので、個人のレコードを削除する場合は、TThing クラスを呼び出して、その個人に関連するものを削除します。トランザクションはネストできないという問題が発生します。最初に TThing を削除し、次に Tperson を削除するトランザクションを再宣言した場合、Tperson でエラーが発生した場合、どうすれば TThing をロールバックできますか?例:procedure Tperson.Drop(const person:String);var sqlString:String; thing:Tthing;begin sqlString := 削除された SQL ステートメント; //TDBOperate_DL 型の DBOperateパラメータとして渡されます。 Self.DBOperate.BeginTrans; Try Thing.Drop(person); // 内部にトランザクションがあります。self.DBOperate.Execute(sqlString); end;end ;ソリューション、2 フェーズ送信、最初にいくつかの背景知識: 2 層システムまたは 3 層システムに関係なく、トランザクション処理は 2 フェーズ送信を通じて実現されます。第 1 フェーズでは、実行された各リソース/レコードがトランザクション環境 (TranscationContext) に書き込まれ、リソース コーディネーターは、参加している各トランザクションの実行が成功したかどうかを順番に問い合わせます。問題がなければ、第 2 フェーズに進みます。実行は、操作をコミットすることで開始されます。 1 つの実行に問題がある場合、リソース コーディネーターは、下位のすべての実行にコミットを中止してデータの元の状態に戻すように通知します。 COM+ のトランザクション操作を参照すると、コンポーネントがトランザクションを必要とする場合、コンポーネントの作成時にトランザクションが開始されており、ルート トランザクションの場合はトランザクションの投票が実行されます。巻き戻された。 (コンポーネントがプーリングをサポートしている場合、これら 2 つの状況はコンポーネントのアクティブ化イベントとスリープ イベントで発生します)。そこで次のようにクラスを定義します。 //統合トランザクション サポートを提供するために使用されるビジネス クラスの祖先クラス TTS_DL = class private isRootTrans:Boolean //ルート トランザクションかどうか isNeedTrans:Boolean //トランザクションが必要かどうか public DBOperate:TDBOperate_DL;データベース インスタンス プロシージャ SetComplete; プロシージャ SetAbort; コンストラクタ Create(const newDBOperate:TDBOperate_DL; needTrans:Boolean);//トランザクション サポート デストラクタが必要かどうかDestroy; override; end; このクラスが作成されると、データベースを操作するクラスのインスタンスを渡すだけでなく、操作がデータベースの読み取りのみである場合には、トランザクションが必要かどうかを判断するためにフラグが渡されます。 、取引の必要はありません。クラスの実装コードは次のとおりです:constructor TTS_DL.Create(const newDBOperate: TDBOperate_DL; needTrans: Boolean);begin継承 Create; self.DBOperate := newDBOperate; //代入にトランザクションが必要かどうか。 if self.isNeedTrans then begin //トランザクション内にある場合、ルート トランザクションではなく、トランザクション コンテキスト内の isCommit の値は変更されません。 self.DBOperate.isInTrans then self.isRootTrans := false else begin self.DBOperate.BeginTrans; // ルート トランザクションの場合、トランザクションを開始します self.isRootTrans := true;コミットフラグを初期化します トランザクションをコミットするにはend;end;destructor TTS_DL.Destroy;begin if self.isNeedTrans then begin // ルート トランザクションの場合、投票結果に従ってトランザクションをコミットまたはロールバックします。 if self.isRootTrans then begin if self.DBOperate.isCommit then self.DBOperate.CommitTrans else self.DBOperate.RollbackTrans end;終了; プロシージャ TTS_DL.SetAbort; 開始 self.DBOperate.isCommit := self.DBOperate.isCommit そして false; //ロールバックエンドに投票;プロシージャ TTS_DL.SetComplete;begin self.DBOperate.isCommit := self.DBOperate.isCommit そして true; //コミットエンドに投票;今回はビジネス クラス Tthing と Tperson に戻ります。 TTS_DL クラス。 Tthing = class(TTS_DL); Tperson = class(TTS_DL); Tthing の削除コードは次のようになります。 . DBOperate.Execute(sqlString); //self 以外の投票。 DBOperate.SetAbort; //Vote rollback raise; end;end; Tperson の削除コードは次のとおりです:procedure Tperson.Drop(const person:String);var sqlString:String;begin sqlString ; もの := Tthing.Create(self.DBOperate,true); //TDBOperate_DL タイプ DBOperate はパラメータとして渡されます。true はトランザクションが必要であることを意味します。 Try Try Thing.Drop(person); self.DBOperate.SetComplete; // 投票のロールバック終了; //忘れずに解放してください end;end; プログラムで使用されるオペレーティング データベース クラス TDBOperate_DL の唯一のインスタンスを忘れずに保持し、トランザクションが必要な場合はできるだけ早く解放してください。終わり。最初のバージョンはレベルが限られており、実際のアプリケーションで改善する必要があります。これは、新しいアイデアを呼び込むための単なる方法です。経験豊富なヒーローに貢献してください。