Hasta aquí ya tenemos un proyecto creado que además cuenta con un formulario principal. Como nuestro servidor de aplicaciones es la que llevará la parte dura, es en ella que debemos de implementar el código necesario para gestionar y controlar la atomicidad de las actualizaciones.
Para empezar, será necesario agregar un Remote Data Module, que en realidad es un COM Automation Server (Servidor de Automatización COM) el que será accesado remotamente por los clientes usando DCOM, HTTP, o Sockets.
- File -> New -> Other -> Multitier -> Remote Data Module
Delphi nos mostrará el asistente solicitando el nombre de nuestro Remote Data Module (También servirá de nombre base para la interfase de la clase ). En el campo CoClass Name asignaremos el nombre de coRDM, como se muestra en el gráfico siguiente:

Presionamos el botón OK y guardamos la unidad como uRDM.pas. Delphi ha generado y añadido al proyecto un archivo llamado NTierXIServer_TLB.pas. Sobre el Remote Data Module, colocaremos los siguientes componentes de acceso a datos, como se muestra en el siguiente grafico.

La descripción detallada de los componentes dbGo que usamos se muestra a continuación.
1 TADOConnection (MDCDSDB),
2 TADOQuery (qryMaster y qryDetail),
2 TDataSetProvider (prvMaster y prvDetail),
TADOConnection, usa la base de datos Northwind del SQL 2000. Al crear nuestra cadena de conección a la base de datos a través del asistente, nos queda algo así:
Provider=SQLOLEDB.1; Password=xxxx; Persist Security Info=True; User ID=sa; Initial Catalog=Northwind; Data Source=jcastillo\sql2000;Use Procedure for Prepare=1; Auto Translate=True; Packet Size=4096; Workstation ID=JCASTILLO
Dependiendo del entorno de trabajo de su red, la cadena de conección no deberá ser necesariamente igual a ésta.
En los componentes TADOQuery, debemos especificar las sentencias SQL que obtendrán los datos de los empleados. Por eso, en la propiedad SQL del qryMaster, escribimos la siguiente sentencia:
select * from employees
Luego, en la propiedad SQL del qryDetail, especificamos la sentencia SQL que obtendrá los datos de los territorios que corresponden a los empleados de la empresa:
select * from EmployeeTerritories
where employeeID=:employeeID
Conectamos el componente prvMaster con el qrymaster a través de la propiedad DataSet. Hacemos lo mismo con los componentes prvDetail y qryDetail.
Llegó el momento de implementar nuestro método personalizado que gestione las actualizaciones directamente a la base de datos. Para eso, vamos a usar una utilidad que viene en Delphi desde hace mucho tiempo, el Type Library (Librería de Tipos).
El Type Library genera archivos binarios del tipo .tlb. A través de ésta herramienta podremos incluir información acerca de tipos, objetos e interfaces expuestas por nuestra aplicación servidor. La información de los objetos en la librería estarán disponibles para nuestra aplicación cliente que construyamos después. Para abrir el Type Library siga los siguientes pasos:
View -> Type Library
En nuestro caso Type Library, nos permitirá declarar el método CDSapplyUpdates para que ésta se encuentre disponible a través de la Interfase del IAppServer.
Seleccionamos la Interfase IcoRDM, y escogemos el icono New Method
desde la barra de herramientas. Ahora el método miembro es añadido al panel de la lista de objetos, solicitando añadir un nombre.
Escribimos el nombre para el método miembro, como se muestra en la figura:

Luego, en la ficha Parameters, creamos los siguientes parametros: vDeltaArray, vProviderArray y Local.

Para implementar los cambios en la interfase, escojemos el ícono
Refresh Implementation, y Delphi generará el siguiente código en la ficha Text:
[
Id(0x0000012D)
]
HRESULT _stdcall CDSapplyUpdates([in] VARIANT * vDeltaArray, [in] VARIANT * vProviderArray, [in] VARIANT_BOOL Local);
Ahora, solo nos queda localizar el nuevo método dentro del código fuente de la unidad del Remote Data Module, si se encuentra en el diseñador, presione F12 para ir al área de código. Aquí completaremos el cuerpo del método con el código necesario para terminar con la implementación.
procedure TcoRDM.CDSapplyUpdates(var vDeltaArray, vProviderArray: OleVariant;
Local: WordBool);
var
i : integer;
LowArr, HighArr: integer;
P: PArrayData;
begin
MDCDSDB.Connected:=true;
MDCDSDB.BeginTrans;
try
LowArr:=VarArrayLowBound(vDeltaArray,1);
HighArr:=VarArrayHighBound(vDeltaArray,1);
P:=VarArrayLock(vDeltaArray);
try
for i:=LowArr to HighArr do
AplicarDelta(vProviderArray[i], P^[i], Local);
finally
VarArrayUnlock(vDeltaArray);
end;
MDCDSDB.CommitTrans;
except
MDCDSDB.RollbackTrans;
end;
end;
Como puede observar, BeginTrans indica el inicio de una transacción explícita, y envuelve las actualizaciones de los ClientDataSets en una transacción. Si alguno de ellos resulta en error, se disparará una excepción, que realizará un Rollback en la transacción; en caso contrario, si todo sale como esperamos se confirma la transacción mediante el CommitTrans.
Observe que llamamos a un procedimiento llamado AplicarDelta. AplicarDelta no ha sido declarada en el Type Library, debido a que no es necesario que las aplicaciones clientes accedan directamente a ella. Al retornar, Delta contendrá un data packet que contiene todos los registros que no se pudieron aplicar a la base de datos. Delphi necesita el nombre del provider, y éste es pasado en el elemento 1 de la variant AProvider.
procedure AplicarDelta(AProvider: OleVariant; var Delta : OleVariant; Local: Boolean);
var
ErrCount : integer;
OwnerData: OleVariant;
begin
if not VarIsNull(Delta) then
begin
if Local then
Delta := (IDispatch(AProvider[0]) as IAppServer).AS_ApplyUpdates(AProvider[1], Delta, 0, ErrCount, OwnerData)
else
Delta := IAppServerDisp(IDispatch(AProvider[0])).AS_ApplyUpdates(AProvider[1], Delta, 0, ErrCount, OwnerData);
if ErrCount > 0 then
SysUtils.Abort; // Esto causa un Rollback
end;
end;
Ahora, sólo nos queda compilar la aplicación y echarlo a correr, si todo nos fue bien, tendremos una pantalla como la siguiente:

Una novedad que debemos indicar es que al crear el Remote Data Module, éste aparece como Available forms (formularios disponibles) y para poder usarlo debemos de crearlo explícitamente mediante el método Create(). Para eso, en el evento Create de nuestro formulario principal del proyecto escribimos el siguiente código:
procedure TfMain.FormCreate(Sender: TObject);
begin
TcoRDM.Create(Self);
end;
También, debemos de resaltar que en Delphi 2007, los servidores COM del tipo out-of-process, como el que acabamos de implementar, ya no se registran en el sistema automáticamente cuando echamos a correr la aplicación. CodeGear ha visto por conveniente, dejarle esta tarea al desarrollador, no se olvide. Una manera de registrar nuestro servidor es añadir el parámetro /regserver en el cuadro de dialogo:
Como se muestra en la figura de abajo.

Finalmente, presionamos F9 para ejecutar la aplicación, que, con la especificación realizada, hará que se registre nuestro Servidor.
Connect with Us