Frage: Ich habe eine Datenbankoperationsklasse TDBPerate_DL geschrieben, um die Operationen in der Datenbank zu vereinheitlichen. Für andere Klassen werden Methoden zum Deklarieren des Transaktionsstarts, zum Festschreiben der Transaktion und zum Zurücksetzen der Transaktion bereitgestellt. TDBOperate_DL = class PRivate ADOC:TADOConnection; isDestroyADOC:Boolean; fIsInTrans:Boolean; //Ob die Transaktion gestartet wurde public isCommit:Boolean; //Ob die Transaktion festgeschrieben werden soll, der Standardwert ist true, wenn eine Klasse gegen die Übermittlung stimmt, ist sie false function IsInTrans:Boolean; TADOConnection );overload; Konstruktor Create(const ServerName,DataBaseName,UserID,PassWord:String);overload;destructor Destroy;override; CommitTrans; procedure RollbackTrans; procedure GetDataset(const sqlString):_Recordset; procedure SetConnection(const newADOC:TADOConnection); ; //Transaktion starten begin self.ADOC.BeginTrans; self.fIsInTrans := true;end;procedure TDBOperate_DL.CommitTrans; //Commit-Transaktion beginne self.ADOC.CommitTrans := false;end;procedure TDBOperate_DL.RollbackTrans; //Rollback-Transaktion beginne self.ADOC.RollbackTrans ; self.fIsInTrans := false;end;function TDBPerate_DL.IsInTrans: Boolean; //Überprüfen Sie, ob die Transaktion gestartet wurde begin result := self.fIsInTrans;end;Schreiben Sie eine TThing-Klasse, um Datensätze über etwas zur Datenbank hinzuzufügen, zu ändern oder zu löschen. Rufen Sie zum Abschluss die Klasse TDBPerate_DL auf. Um den Aufruf zu vereinfachen, werden die relevanten Transaktionen in der TThing-Klasse platziert, und es besteht keine Notwendigkeit, die Transaktion bei externen Aufrufen zu berücksichtigen. Zum Beispiel: procedure Tthing.Drop(const thing:String);var sqlString:String;begin sqlString := gelöschte SQL-Anweisung; // DBOperate ist eine private Variable vom Typ TDBPerate_DL, die beim Erstellen eines Tthing übergeben wird Klasseninstanzparameter. Versuchen Sie es mit self.DBOperate.Execute; außer self.DBOperate.RollbackTrans; später habe ich eine TPerson-Klasse zum Hinzufügen, Ändern oder Löschen von Informationen über Personen geschrieben. Dieselbe Transaktion wird in der TPerson-Klasse platziert. Wenn ich nun den Datensatz einer Person löschen möchte, rufe ich die TThing-Klasse auf, um Dinge zu löschen, die sich auf die Person beziehen. Es entsteht ein Transaktionsproblem: Transaktionen können nicht verschachtelt werden. Wenn Sie zuerst TThing löschen und dann die Transaktion zum Löschen von TPerson erneut deklarieren und TPerson einen Fehler macht, wie können Sie TThing dann zurücksetzen? Zum Beispiel: procedure Tperson.Drop(const person:String);var sqlString:Thing;begin sqlString := done SQL-Anweisung thing := Tthing.Create(self.DBOperate); //Der DBOperate vom Typ TDBOperate_DL wird als Parameter übergeben. Self.DBOperate.BeginTrans; Try Thing.Drop(person); end;end ;Lösung, zweistufige Übermittlung, zunächst etwas Hintergrundwissen: Unabhängig vom zweistufigen oder dreistufigen System wird die Transaktionsverarbeitung durch zweistufige Übermittlung realisiert. In der ersten Phase wird jede ausgeführte Ressource/jeder Datensatz in die Transaktionsumgebung (TranscationContext) geschrieben, und dann fragt der Ressourcenkoordinator nacheinander ab, ob die Ausführung jeder teilnehmenden Transaktion erfolgreich ist, und tritt in die zweite Phase ein Die Ausführung beginnt mit dem Commit seiner Operationen. Wenn bei einer Ausführung ein Problem auftritt, benachrichtigt der Ressourcenkoordinator alle untergeordneten Ausführungen, das Commit aufzugeben und den ursprünglichen Zustand der Daten wiederherzustellen. Bezogen auf den Transaktionsvorgang von COM+: Wenn eine Komponente eine Transaktion erfordert, wurde die Transaktion bereits gestartet, wenn die Komponente zerstört wurde. Wenn es sich um eine Stammtransaktion handelt, wird die Transaktion festgeschrieben zurückgerollt. (Wenn die Komponente Pooling unterstützt, treten diese beiden Situationen bei den Komponentenaktivierungs- und Ruhezustandsereignissen auf.) Daher definieren wir eine Klasse wie folgt. //Vorfahrenklasse der Business-Klasse, die zur Bereitstellung einheitlicher Transaktionsunterstützung verwendet wird TTS_DL = class private isRootTrans:Boolean; //Ob es sich um eine Root-Transaktion handelt, //Ob eine Transaktion erforderlich ist public DBOperate:TDBOperate_DL; Betreibt die Datenbankinstanz procedure SetComplete; procedure SetAbort; Konstruktor Create(const newDBOperate:TDBOperate_DL; needTrans:Boolean);//Ob ein Destruktor für die Transaktionsunterstützung erforderlich ist Destroy; override; end; Wenn diese Klasse erstellt wird, wird zusätzlich zur Übergabe der Instanz der Klasse, die die Datenbank betreibt, ein Flag übergeben, um zu bestimmen, ob eine Transaktion erforderlich ist, da die Operation nur zum Lesen der Datenbank dient Es ist keine Transaktion erforderlich. Der Klassenimplementierungscode lautet wie folgt: Konstruktor TTS_DL.Create(const newDBOperate: TDBOperate_DL; needTrans: Boolean);begin inherited Create; self.DBOperate := newDBOperate; self.isNeedTrans := needTrans; //Ob eine Transaktion erforderlich ist if self.isNeedTrans then begin //Wenn es sich um eine Transaktion handelt, handelt es sich nicht um die Stammtransaktion, und der Wert von isCommit im Transaktionskontext bleibt unverändert, wenn self.DBOperate.isInTrans then self.isRootTrans := false begin self.DBOperate.BeginTrans; //Wenn es die Root-Transaktion ist, starte die Transaktion self.isRootTrans := true; Initialisieren Sie das Commit-Flag, um die Transaktion zu committen. Ende; Ende; Destruktor TTS_DL.Destroy; beginnen, wenn self.isNeedTrans, dann beginnen //Wenn es sich um eine Root-Transaktion handelt, wird die Transaktion gemäß den Abstimmungsergebnissen festgeschrieben oder zurückgesetzt. if self.DBOperate.isCommit then self.DBOperate.CommitTrans else self.DBOperate.RollbackTrans end; end; procedure TTS_DL.SetAbort;begin self.DBOperate.isCommit := self.DBOperate.isCommit And false; //Vote to rollbackend;procedure TTS_DL.SetComplete;begin self.DBOperate.isCommit := self.DBOperate.isCommit And true; //Vote to commitend;Zurück zu den Geschäftsklassen Tthing und Tperson, dieses Mal werden alle von geerbt TTS_DL-Klasse. Tthing = class(TTS_DL); Tperson = class(TTS_DL); Der Löschcode von Tthing sollte wie folgt lauten: procedure Tthing.Drop(const thing:String);var sqlString:= done SQL-Anweisung; . DBOperate.Execute(sqlString); self. DBOperate.SetAbort; //Vote rollback raise; end;end; Der Löschcode für Tperson lautet wie folgt: procedure Tperson.Drop(const person:String);var sqlString; thing:Tthing;begin sqlString := gelöschte SQL-Anweisung ; thing := Tthing.Create(self. DBOperate,true); //TDBOperate_DL Typ DBOperate wird als Parameter übergeben, true bedeutet, dass eine Transaktion erforderlich ist. Versuchen Sie es mit Thing.Drop(person); Self.DBOperate.SetComplete; //Abstimmungs-Rollback end; //Denken Sie daran, end;end; freizugeben. Denken Sie daran, die einzige im Programm verwendete Instanz der Betriebsdatenbank TDBOperate_DL beizubehalten, und denken Sie daran, die Business-Klasseninstanz freizugeben. Wenn eine Transaktion erforderlich ist, geben Sie sie so früh wie möglich frei. Erledigt. Die erste Version hat ein begrenztes Niveau und muss in der praktischen Anwendung verbessert werden. Es ist nur eine Möglichkeit, neue Ideen anzulocken. Bitte bringen Sie erfahrene Helden mit.