18 de octubre de 2002

COM+ con VFP 7.0 - Parte 3

Publicado originalmente en FoxTalk.
Traducción de Jorge Espinosa.

Las transacciones son una parte importante de cualquier mecanismo de actualización de datos. La parte 3 de Craig Berntson nos introduce en la Coordinación de Transacciones Distribuidas y explica como usar las transacciones bajo COM+.

Transacciones

Sin ellas no podemos estar seguros que los datos están siendo escritos en todas las tablas involucradas en la actualización. Antes de introducirnos en como trabajan las transacciones en COM+ hagamos una revisión rápida de transacciones.

Revisión de Transacciones

Joe quiere transferir $100 de su cuenta de pagos a su cuenta de cheques. El camina hacia el cajero, inserta su tarjeta, presiona el botón para empezar la transferencia. Durante la escena, esta transferencia puede se lograda de dos maneras. La primera manera es que el balance de la cuenta de pagos de Joe puede ser reducida por $100 y el balance de su cuenta de cheques incrementada por $100. La segunda opción es que el balance de su cuenta de cheques puede ser incrementada y el balance de su cuenta de pagos puede ser decrementada. Pero que pasa si allí sucede una caída del sistema entre las dos actualizaciones? Bajo la primera escena Joe no estaría feliz. El perdió $100. En el segundo ejemplo Joe está muy feliz. El es $100 mas rico pero el banco tiene ahora una pérdida de $100. Lo que nosotros queremos es esto, en el evento de la caída mencionado, o ambas cuentas deben se actualizadas o ninguna debe ser actualizada. El propósito de la transacción es asegurar que esto pase. Las transacciones deben seguir la regla ACID, que es, atomicidad, consistencia, aislamiento y durabilidad.

La Atomicidad significa que o todas o ninguna de las actualizaciones se ejecuten. La Consistencia significa que si una transacción falla los datos son retornados al mismo estado que tenían antes de empezar la transacción. El aislamiento significa que una transacción no sepa que otra transacción se está haciendo. Finalmente, la Durabilidad significa que el estado de la transacción se guarda, no importa que pase en el sistema.

Esto es manejado generalmente a través de un log de transacciones.

Podemos implementar transacciones en nuestros datos de VFP al usar los comandos BEGIN TRANSACTION / END TRANSACTION / ROLLBACK. El pseudo código muestra un procedimiento de ejemplo:
BEGIN TRANSACTION
LlSavingsOk = UpdateSavings(-100)
LlCheckingOk = UpdateChecking(100)
IF llSavings and llChecking
 END TRANSACTION
Else
 ROLLBACK
ENDIF
Las transacciones en VFP solo trabajan con datos de VFP, y las transacciones de VFP carecen de la regla de la durabilidad de ACID. No hay ningún log de transacciones.

Si estuviésemos usando SQL Server necesitaríamos usar un mecanismo diferente. Podemos usar comandos de ADO para llamar a SQL server cuando empieza o termina una transacción o podemos codificar en un stored procedure.

Sin embargo, que pasaría si la cuenta de pagos estuviese en SQL Server y los datos de la cuenta de cheques estuviesen en Oracle? Las transacciones de Sql Server solamente trabajarían en Sql Server, y las transacciones de Oracle solamente trabajarían con Oracle. Necesitamos una sola transacción que trabaje con ambas base de datos. Aquí es donde entra la Coordinación de Transacción Distribuida (DTC).

Usando el DTC

El DTC nos permite tener transacciones que crucen base de datos. Esto significa que tenemos datos en ambos, Sql Server y Oracle, que actualizaríamos por la misma transacción. Bajo MTS y VFP 6, los datos de Fox no podrían participar en la transacción DTS.(Esto cambia bajo COM+ y VFP7. Veremos acerca de esto mas adelante). Volviendo al DTC.

El DTS usa un commit en dos fases. Básicamente, en la primera fase, el DTS pregunta a la base de datos si puede hacer una actualización. Si todos los datos responden que si a esa pregunta, comienza la segunda fase, en el que el DTS le dice a la base de datos que debe actualizar los datos. Si alguna de las base de datos responde que no el DTS le dice a las bases de datos que se hace un Roll Back de la actualización.

Veamos como las transacciones son manejadas bajo MTS:
DEFINE CLASS Math AS SESSION OLEPUBLIC
FUNCTION Multiply(tnNum1, tnNum2)
LOCAL lnResult, LomTX, LoContext

** Creamos una referencia al objeto MTS
LoMtx = CREATEOBJECT("MTXAS.APPSERVER.1")

** Creamos una referencia al objeto Contexto
LoContext = loMTX.GetObjectContext()

lnResult = tnNum1*tnNum2

** Cierra la transaccion si existe y le avisa a MTS que ha finalizado con el uso del componente

LoContext.SetComplete()

** Si existiera un error podriamos abortar la transacción y avisarle a MTS que finalizamos
** Con el componente usando loContext.SetAbort()

RETURN lnResult
ENDFUNC
ENDDEFINE
Note que cuando nosotros hacemos Commit o abortamos la transacción, MTS también descargará el componente.

Esto significa que si el próximo comando en nuestra aplicación necesita el componente, tendremos que hacer otro CREATEOBJECT() en el cliente. Veamos como cambia esto en COM+:
 
DEFINE CLASS Math AS SESSION OLEPUBLIC
FUNCTION Multiply(tnNum1, tnNum2 as Number);
 AS Number HELPSTRING "Multiplica ;
  Dos números y devuelve el resultado"

LOCAL lnResult, LomTX, LoContext, loContextState, ;
 LlDone, llGetDone, lnTxnState, lnGetTxnState

LlDone = .T.
LlGetDone = .F.
LnTxnState = 1
LnGetTxnState = 0

** Creamos una referencia al objeto MTS
LoMtx = CREATEOBJECT("MTXAS.APPSERVER.1")

** Creamos una referencia al objeto Contexto
LoContext = loMTX.GetObjectContext()

** Crea una interfaz al estado del Contexto
LoContextState = GETINTERFACE(loContext, "iContextState")

lnResult = tnNum1*tnNum2

** Establece el seteo de la Transacción (Consistencia)
** 0 = Commit,   1 = Abort

LoContextState.SetMyTransactionVote(lnTxnState)
LoContextState.GetMyTransactionVote(@lnGetTxnState)

** Lleva adelante el seteo de Activacion
** .T. = Desactiva ,   .F. = Deja Activado

loContextState.SetDesctivateOnReturn(llDone)
loContextState.GetDeactivateOnReturn(@llGetDone)

RETURN lnResult
ENDFUNC
ENDDEFINE
En este ejemplo, podemos hacer Commit o abortar la transacción con SetMyTransactionVote, pero tenga en cuenta la instancia del componente permanecerá activa hasta que explícitamente llamemos a SetDeactivateOnReturn con .T. como parámetro.

Ahora estará preguntándose donde encaja el DTC en esto COM+ automáticamente llama al DTC por usted

El DTC habla con la base de datos a través del uso de Resource Manager.

MTS y COM+ ya vienen con Resource Managers para Oracle y SQL Server, pero no para VFP. Es por esto que los datos de VFP no podrían tomar parte en una transacción MTS.

Resulta que Resource Managers es muy difícil para implementar. Entonces, por esto es que COM+ es llamado Compensating Resource Managers(CRMs). CRMs son mas fáciles de implementar que un Resource Managers. Al usar un CRM podemos tener nuestros datos involucrados en una transacción DTC.

Un CRM consiste en dos partes, la CRM Worker y la CRM Compensator. Esto corresponde a las dos fases del commit del DTC. Un detalle en discusión sobre el CRM está fuera del alcance de este capítulo. Sin embargo, VPF 7 viene con un ejemplo de aplicación CRM. Encontrará esto en las carpetas SAMPLES\COM+\CRM bajo la instalación de su VFP 7.

Configurando transacciones COM+

Como muchos de los rasgos en COM+, las transacciones son manejadas en tiempo de ejecución. Abrir el Component Service Manager (applet) y elegir uno de sus componentes. Click derecho en el componente y seleccione propiedades, seleccione el tab de transacciones. Verá cinco opciones de transacciones.(figura1 y tabla1)

También notará el ckeck box "Override global transaction timeout value". Cuando seleccione Required o Required new transaction, este ckeckbox estará habilitado. Entonces puede ingresar el número de segundos que correrá la transacción antes del time out.

Esto fue un acercamiento a las transacciones. En la parte 4 daremos un vistazo a las ventajas de COM+ con Queued Components.



Figura 1.

Tabla 1. Tipos de transacciones soportados por componentes COM+.
SeetingDescripción
DisabledLa transacción no se necesita. Elija esta cuando no necesite la sobrecarga de trabajo que implica generar una transacción, por ejemplo un componente que no tiene que actualizar ningún dato.
Not SupportedImpide a un componente usar la transacción, sin tener en cuenta el estado transaccional de la llamada al componente.
SupportedEl componente participa en la transacción si una está activa.
RequiredEl componente participa en la transacción si una está activa. Si no hay ninguna transacción activa, genera una nueva.
Requires NewUna transacción nueva es generada siempre.

Craig Berntson es Microsoft Certified Solution Developer y fue nombrado cuatro veces Microsoft Most Valuable Profesional. Disertante de varias conferencias de FoxPro en todo EEUU y eventos de Microsoft en Salt Lake. Es Presidente del Salt Lake City Fox Users Group y actualmente ingeniero de software senior para 3m Health Information Systems.
Jorge A. Espinosa, Buenos Aires (Capital Federal), Argentina, es Analista Programador y MCP. Dedicado al desarrollo de sistemas desktop desde el año 1987; siempre en el entorno xBase y en Visual Fox Pro desde la version 3.0. Hoy Gerente de Sistemas en Droguería Saporiti SACIFIA.

No hay comentarios. :

Publicar un comentario