Pregunta: Escribí una clase de operación de base de datos TDBPerate_DL para unificar las operaciones en la base de datos. Se proporcionan métodos para declarar el inicio de una transacción, confirmar una transacción y revertir una transacción para que otras clases los llamen. TDBOperate_DL = class PRivate ADOC:TADOConnection; ADOQ:TADOQuery; isDestroyADOC:Boolean; ¿Destruir tu propio ADOC? fIsInTrans:Boolean; //Si la transacción ha comenzado public isCommit:Boolean; //Si se confirma la transacción, el valor predeterminado es verdadero, si una clase vota en contra del envío, es falso function IsInTrans:Boolean constructor Create(const newADOC: TADOConnection); sobrecarga; constructor Create(const ServerName,DataBaseName,UserID,PassWord:String);sobrecarga; destructor Destroy;override procedimiento; CommitTrans; procedimiento RollbackTrans; procedimiento Execute(const sqlString:String); función GetDataset(const sqlString:String):_Recordset; procedimiento TDBOperate_DL.BeginTrans; ; //Iniciar transacción comenzar self.ADOC.BeginTrans; self.fIsInTrans := true;end;procedimiento TDBOperate_DL.CommitTrans; //Comenzar transacción de confirmación self.ADOC.CommitTrans; self.fIsInTrans := false;end;procedimiento TDBOperate_DL.RollbackTrans; //Comenzar transacción de reversión self.ADOC.RollbackTrans ; self.fIsInTrans := false;fin;función TDBPerate_DL.IsInTrans: booleano; //Verifique si la transacción ha comenzado start result := self.fIsInTrans;end;Escriba una clase TThing para agregar, modificar o eliminar registros sobre algo en la base de datos, llame a la clase TDBPerate_DL para completar. Para facilitar la llamada, las transacciones relevantes se colocan en la clase TThing y no es necesario considerar la transacción al realizar llamadas externas. Por ejemplo: procedimiento Tthing.Drop(const thing:String);var sqlString:String;begin sqlString := instrucción SQL eliminada; self.DBPerate.BeginTrans // DBOperate es una variable privada de tipo TDBPerate_DL, que se pasa al crear un Tthing; parámetros de instancia de clase. pruebe self.DBOperate.Execute(sqlString); self.DBOperate.CommitTrans; excepto self.DBOperate.RollbackTrans; end;end; más tarde, escribí una clase TPerson para agregar, modificar o eliminar información sobre las personas en el registro de la base de datos. La misma transacción se coloca en la clase TPerson. Ahora, cuando quiero eliminar el registro de una persona, llamo a la clase TThing para eliminar cosas relacionadas con la persona. Surge un problema de transacción: las transacciones no se pueden anidar. Si primero elimina TThing y luego vuelve a declarar la transacción para eliminar TPerson, si TPerson comete un error, ¿cómo puede revertir TThing? Por ejemplo: procedimiento Tperson.Drop(const person:String);var sqlString:String; thing:Tthing;begin sqlString := instrucción SQL eliminada; thing := Tthing.Create(self.DBOperate); //El DBOperate del tipo TDBOperate_DL; se pasa como parámetro. Self.DBOperate.BeginTrans; Pruebe Thing.Drop(person); // Hay una transacción dentro, consulte el código anterior Self.DBOperate.RollbackTrans; end;end;Solución, envío en dos fases, primero algunos conocimientos previos: no importa el sistema de dos o tres niveles, el procesamiento de transacciones se realiza mediante el envío en dos fases. En la primera fase, cada recurso/registro ejecutado se escribe en el entorno de transacción (TranscationContext) y luego el coordinador de recursos pregunta secuencialmente si la ejecución de cada transacción participante es exitosa. Si no hay problemas, ingresa a la segunda fase. la ejecución comienza con la confirmación de sus operaciones. Si hay un problema con una ejecución, el coordinador de recursos notifica a todas las ejecuciones subordinadas para que abandonen el compromiso y restablezcan el estado original de los datos. En referencia a la operación de transacción de COM+, si un componente requiere una transacción, la transacción ya se inició cuando se crea el componente. Cuando se destruye el componente, se realiza una votación de transacción. Si es una transacción raíz, la transacción se confirma o. retrocedido. (Si el componente admite la agrupación, estas dos situaciones ocurren en los eventos de activación y suspensión del componente). Entonces definimos una clase de la siguiente manera. //Clase ancestral de la clase empresarial, utilizada para proporcionar soporte de transacciones unificadas TTS_DL = class private isRootTrans:Boolean; //Si es una transacción raíz isNeedTrans:Boolean //Si se requiere una transacción public DBOperate:TDBOperate_DL //Clase que opera la base de datos Procedimiento de instancia SetComplete; procedimiento SetAbort constructor Create(const newDBOperate:TDBOperate_DL; needTrans:Boolean);// Si se requiere el destructor de soporte de transacciones Destroy; override; end; Cuando se crea esta clase, además de pasar la instancia de la clase que opera la base de datos, se pasa un indicador para determinar si se requiere una transacción, porque si la operación es solo para leer la base de datos. , no hay necesidad de realizar una transacción. El código de implementación de la clase es el siguiente: constructor TTS_DL.Create(const newDBOperate: TDBOperate_DL; needTrans: Boolean);begin heredado Create; self.DBOperate := newDBOperate; self.isNeedTrans := needTrans //Si se requiere una transacción para la asignación; if self.isNeedTrans luego comenzar // Si está en una transacción, no es la transacción raíz y el valor de isCommit en el contexto de la transacción permanece sin cambios si self.DBOperate.isInTrans luego self.isRootTrans := false else comienza self.DBOperate.BeginTrans; // Si es la transacción raíz, inicia la transacción self.isRootTrans := true; Inicialice el indicador de confirmación Para confirmar la transacciónend;end;destructor TTS_DL.Destroy;begin if self.isNeedTrans luego comience // Si es una transacción raíz, confirme o revierta la transacción de acuerdo con los resultados de la votación if self.isRootTrans entonces comience if self.DBOperate.isCommit luego self.DBOperate.CommitTrans else self.DBOperate.RollbackTrans end; finalizar; procedimiento TTS_DL.SetAbort; comenzar self.DBOperate.isCommit: = self.DBOperate.isCommit y falso; //Votar para rollbackend;procedimiento TTS_DL.SetComplete;begin self.DBOperate.isCommit := self.DBOperate.isCommit And true; //Votar para confirmar;Volver a las clases de negocios Tthing y Tperson, esta vez Todas se heredan de Clase TTS_DL. Tthing = class(TTS_DL); Tperson = class(TTS_DL); El código de eliminación de Tthing debe ser el siguiente: procedimiento Tthing.Drop(const thing:String);var sqlString:String;begin sqlString := declaración SQL eliminada; .DBOperate.Execute(sqlString); self.DBOperate.SetComplete //Envío de voto excepto self. DBOperate.SetAbort; //Vote rollback rise; end;end; El código de eliminación para Tperson es el siguiente: procedimiento Tperson.Drop(const person:String);var sqlString:String;begin sqlString := declaración SQL eliminada ; cosa := Tthing.Create(self. DBOperate,true); // TDBOperate_DL tipo DBOperate se pasa como parámetro, verdadero significa que se requiere una transacción. Pruebe Try Thing.Drop(person); Self.DBOperate.Execute(sqlString); self.DBOperate.SetComplete; // Envío de voto excepto self. // Recuerde liberar end;end; Recuerde mantener la única instancia de la clase de base de datos operativa TDBOperate_DL utilizada en el programa y recuerde liberar la instancia de clase empresarial. Si se requiere una transacción, libérela lo antes posible. hecho. La primera versión tiene un nivel limitado y necesita ser mejorada en aplicaciones prácticas. Es solo una forma de atraer nuevas ideas. Por favor, haga que contribuyan héroes experimentados :)