Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Providers
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-11-2007
juniorSoft juniorSoft is offline
Miembro
 
Registrado: abr 2005
Posts: 178
Poder: 22
juniorSoft Va por buen camino
he estado buscando documentacion en varios sitios

y me ha llegado una idea


para simplificar mas la explicacion de lo que quiero hacer

es solo crear un metodo remoto en la capa intermedia que sea el encargado de mandar las actualizaciones al servidor sql del contenido de la cache de los clientdataset en vez de utilizar el metodo applyupdate en la capa cliente de dicho componente ya que hay demasiadas relaciones complejas entre tablas. y queria envolverlas todas en una transaccion. Sé que el componente provider envuelve en una transaccion los datos que se envian del clientdataset al ejecutar el metodo applyupdate pero eso es solo si todas las tablas estan relacionadas en la capa intermedia.

para que me comprendan mejor

supongamos que tengo una funcion llamada serv que ya me devuelve el servidor de capa intermedia para poder ejecutar los metodos remotos entonces seria

serv.actualizardatos(clientdataset1.data, clientdataset2.data... )

y que sea ese metodo el que se encargue de la actualizcion

y muchas gracias por su interes...
Responder Con Cita
  #2  
Antiguo 16-11-2007
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.614
Poder: 32
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Smile

Hola Juniorsoft, creo que ya entendí el punto.

Me he topado con la misma inquietud y por ello hace poco terminé la versión alfa de un derivado de TClientDataSet con el que puedes hacer un ApplyUpdates "transaction-aware" (para esas ocaciones en que uno quiere manejar varios conjuntos de datos en una sóla transacción).

Pero analicemos el problema por la vía de una solución totalmente nativa, considerando este seudocódigo:


StartTransaction

dt1.ApplyUpdates
dt2.ApplyUpdates
dt3.ApplyUpdates

If todo bien Then
Commit
Else
Rollback



Dinos, ¿cuál es el problema concretísimo que te surgiría con esta organización de instrucciones?
Responder Con Cita
  #3  
Antiguo 16-11-2007
juniorSoft juniorSoft is offline
Miembro
 
Registrado: abr 2005
Posts: 178
Poder: 22
juniorSoft Va por buen camino
ok

cuando yo tengo clientdataset anidados maestros- detalles relacionados en el modulo de datos remoto es facil manejar la transaccion de varios dataset ya que el clientdataset maestro me trae los campos de tipo dataset que se relacionaron en los componentes sql del modulo remoto y la transaccion por defecto del provider los envuelve a todos e incluso puedo llamar storeprocedure dentro de los eventos del provider y estos quedan envueltos tambien en la transaccion.

Pero lo que quiero hacer es un formulario pequeño que me maneje los tipos pagos ya sea en efectivo, cheque o tarjeta y que este formulario me sirva no solo para las ventas sino que tambien me sirva para otros mantenimientos como por ejemplo cuentas por cobrar sin tener que hacer nuevas relaciones de las mismas tablas para el mismo proposito, aclarando que para hacer un pago se pueden utilizar los tres tipos de pago para completar el total a pagar y es donde entra en juego la tabla detallesdepago que tiene una relacion uno a uno con estos tipos de pago. si hago la relacion directa en el modulo de datos remoto por ejemplo con ventas, ya no podre utilizar esos mismos componentes sql para utilizarlos en la relacion con cuentas por cobrar.

si se pueden separar los applyupdates uno para la factura en si y otro para los pagos pero que queden envueltos los dos en una misma transaccion como el ejemplo que escribiste

si has chequeado en la cara oculta de delphi 4 en el capitulo de midas su autor escribio un ejemplo para delphi 3 de un metodo remoto que es el encargado de actualizar los datos para envolver en una transaccion por que los clientdataset tienen envuelta la transaccion a partir de delphi 4

gracias por tu ayuda...
Responder Con Cita
  #4  
Antiguo 17-11-2007
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.614
Poder: 32
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cool

Hola de nuevo.

Cita:
Empezado por juniorSoft Ver Mensaje
...si se pueden separar los applyupdates uno para la factura en si y otro para los pagos pero que queden envueltos los dos en una misma transaccion como el ejemplo que escribiste...
Bueno, estrictamente hablando, las "aplicaciones al servidor" de los dos conjuntos de datos sí quedan envueltas en la misma transacción aunque ellos no estén relacionados entre sí.

La duda que tengo sobre tu planteamiento es:

1. Si no sabes que desde tu aplicación cliente puedes controlar el inicio y cierre de la transacción, evitando que eso lo haga de manera implícita un componente proveedor, y con ello poder envolver en una transacción varios conjuntos de datos no relacionados entre sí (aunque esto depende del modo en que se configure el servidor de aplicaciones).

2. Si, conociendo esa capacidad, te preocupa entonces lo que pasa con la memoria de los conjuntos de datos que sí lograron aplicar los cambios de manera exitosa, cuando la transacción tuvo que ser revertida (rollback) debido a un subsiguiente conjunto de datos que no logró hacer sin errores su ApplyUpdates.

Todo lo que has planteado está muy completo, y ayuda a entender muchas cosas, pero sigue quedando un poquitín abstracto. Tomemos dos conjuntos de datos clientes llamados dt1 y dt2, los cuales están enlazados a diferentes proveedores de la capa intermedia (no están relacionados como maestro-detalle).

¿Qué problema te representa que lo hagas de esta manera?

Código Delphi [-]
  Serv.IniciarTransaccion;

  Try
    dt1.Append;
    dt1.FieldByName ('A').Value := 1;
    dt1.Post;

    dt2.Append;
    dt2.FieldByName ('A').Value := 1;
    dt2.Post;

    If (dt1.ApplyUpdates (0) = 0) And (dt2.ApplyUpdates (0) = 0) Then
      Serv.CometerTransaccion
    Else
      Serv.RevertirTransaccion;
  Except
    If Serv.EnTransaccion Then
      Serv.RevertirTransaccion;

    Raise;
  End;

Yo veo uno. El de que si falla dt2.ApplyUpdates y se revierte (rollback) la transacción, podrás revertir también la memoria de dt2 (con su método CancelUpdates o su propiedad SavePoint). Pero a dt1 ya no lo podrás regresar a su estado previo debido a que ya limpió el "ChangeLog" por no haber tenido errores su respectivo ApplyUpdates. Solución típica y nada eficiente: refrescar dt1. Y esa es una de las razones por las cuales he estado trabajando en el TMagiaClientDataSet (un derivado con ciertas capacidades transaccionales).

Pero no estoy seguro sí esto te preocupa a ti también, o es otra cosa de menor, igual o mayor importancia. Esperamos tus comentarios.

Un abrazo que no se revierte.

Al González.

Última edición por Al González fecha: 17-11-2007 a las 10:13:24.
Responder Con Cita
  #5  
Antiguo 19-11-2007
juniorSoft juniorSoft is offline
Miembro
 
Registrado: abr 2005
Posts: 178
Poder: 22
juniorSoft Va por buen camino
Gracias AL Gonzalez

Yo creo que andamos por el mismo camino y eso es una de las cosas q mas me preocupa cuando tengo que hacer applyUpdate a conjuntos de datos que estan conectados a diferentes provider y que deben guardar los datos en una misma transaccion. Entoces ese componente q estas desarrollando si esta por donde yo estoy pensando debe conectarse con varios provider a la vez y cuando se le de applyupdate al componente, este los envuelva todos en una misma transaccion y si se produce cualquier error se queda el logchange como antes de darle applyupdate. agradezco tus respuestas ya que nos vamos aclarando en un problema comun que le sucede a muchos de nosotros.
Responder Con Cita
  #6  
Antiguo 19-11-2007
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.614
Poder: 32
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Smile

Grosso modo, mi solución tiene que ver con un sistema de puntos de restauración (save points) universales encadenables, implementados en clases derivadas de TSQLConnection y TClientDataSet. Cuando uno de estos conjuntos de datos cliente hace ApplyUpdates, mira si hay un punto padre "marcado" (transacción iniciada en el servidor), en cuyo caso, efectivamente, conserva el ChangeLog tras la operación. Pero debe realizarse el ApplyUpdates por cada conjunto de datos, como estamos acostumbrados. Cuando ese punto padre se confirma (Commit de transacción), todos esos conjuntos de datos "hijos" de la transacción y pendientes de confirmar hacen su MergeChangeLog .

Pero para no ir tan lejos, te comento que la clave para conservar el ChangeLog después de un ApplyUpdates es evitar que se ejecute el método TCustomClientDataSet.MergeChangeLog cuando realizas esa operación.

En el código fuente de DBClient.pas podrás observar que ApplyUpdates llama al método Reconcile, y éste a MergeChangeLog cuando el envío al servidor no tuvo errores. Como Reconcile y MergeChangeLog no son métodos virtuales, no pueden ser redefinidos (Override) en una clase derivada. Entonces, si se quiere evitar que un ApplyUpdates termine llamando a MergeChangeLog, toca redefinir el propio método ApplyUpdates, el cual sí es virtual.

Puedes reescribir el código de dicho método en una clase derivada "TMiClientDataSet", evitando que se llame a Reconcile cuando DoApplyUpdates (otro método involucrado ahí) no regrese errores. De esa manera consigues que el registro de cambios (ChangeLog) permanezca intacto aún después de aplicar todas las actualizaciones al servidor.

Más adelante, cuando hagas el Commit o el Rollback de la transacción, podrás llamar directamente a MergeChangeLog o a CancelUpdates, respectivamente. De esta forma logras envolver a cualquier grupo de objetos TClientDataSet en una transacción.

Espero te sea de utilidad. Síguenos contando sobre tus progresos en el caso.

Un abrazo virtual.

Al González.

Última edición por Al González fecha: 19-11-2007 a las 20:37:22.
Responder Con Cita
  #7  
Antiguo 19-11-2007
juniorSoft juniorSoft is offline
Miembro
 
Registrado: abr 2005
Posts: 178
Poder: 22
juniorSoft Va por buen camino
ok gracias por tu respuesta,

entoces los pasos son
Redefinir el metodo applyupdate para hacer una condicion preguntando por el metodo doapplyupdate que de seguro es una funcion si este metodo es mayor a cero entonces que ejecute el metodo concile

se podria hacer una clase interpuesta de la clase tclientdataset

Tclientdataset = class(dbclient.Tclientdataset)
procedure applyupdate(...);override;

seria algo como
Tclientdataset.applyupdate(....);
begin
if doapplyupdate(...) > 0 then
self.concile(..);
.
.
.
end;

a ver si estoy captando tu idea, por favor me corriges si estoy perdido en algo..
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
cache con idhttp mak8888 Internet 0 10-09-2007 12:38:44
tamaño de cache de bd omarbrdz Firebird e Interbase 3 14-09-2005 15:26:39
IBDataset actualizacion en caché Osorio Conexión con bases de datos 0 07-07-2005 19:06:07
Problemas con la cache usando IBX glopez Firebird e Interbase 5 01-09-2004 17:07:52
Transacciones y/o cache kayetano MySQL 1 25-06-2003 20:30:46


La franja horaria es GMT +2. Ahora son las 01:22:18.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi