Club Delphi  
    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 08-11-2012
Avatar de Maniches
Maniches Maniches is offline
Miembro
 
Registrado: nov 2012
Ubicación: Lima - Perú
Posts: 67
Poder: 12
Maniches Va por buen camino
Thumbs up DataSnap XE3 - Actualización masiva de datasets con datasnap server.

Hola Amigos de ClubDelphi

La idea de crear este hilo es para resolver la actualización de multiples datasets usando sus Deltas hacia un servidor datasnap y que luego de haber actualizado la información en el motor de base datos estos Deltas se actualicen en los ClientdataSets del Cliente. Puede ser mediante RECONCILE o otro forma que se vea conveniente.

Hay que ponerse en el caso que una cabecera tienen muchos detalles y estos detalles tienen subdetalles exagerando pueden llegar a 5 ó 6 niveles. Para complicar el tema se imaginan si este tiene entidad de relación entre sus tablas, con los famosos atributos IDENTITY's.

1. Seria un poco riesgoso hacer un ApplyUpdate por cada Datasets. ya que tendría que actualizar desde la tabla bebé para llegar al papá(cabecera) si todo no esta en una transacción podríamos tener problemas en la actualización en la base datos.
2. Si luego de hacer la actualización a la base datos viene otro problema ya que hay que refrescar el cache de los ClientDataSets por el lado del cliente, la forma sencilla seria refrescar cadadataset con Close/Open o Refresh, esto originaria ejecutar nuevamente las consultas por cada Dataset.


He preparado un ejemplo que voy a adjuntar para todos los interesados. Ya que todos pueden dar sus aportes para llegar a la solución del tema Publicado.
Decirles también que esto que estoy compartiendo actualmente está funcionando con componentes ADO, DCOM, MIDAS y SQL Server. La idea es que funcione con DATASNAP también.

Explico un poco el ejemplo que estoy compartiendo:

El ejemplo es sencillo y no tiene todo el mundo de datasets que menciones anteriormente, pero solucionando el problema con uno ya los demas cada amigo del foro lo va usar a su criterio. La idea es que toda la actualización sea controlado en una sola transacción y también decirles que la idea es trabajar con atributos de tipo IDENTITY como PK y entidad de relacion con FK

Servidor:
Se ha creado una conexión a una tabla users que también comparto el script en el archivo. Dentro del servidor se ha creado un método llamado "UpdateDeltas" que este recibe los nombres de los Providers y Deltas a Actualizar. Si revisan el código ahí verán que todo eso se envía en un arreglo de Variants.
Según las pruebas que he realizado con el ejemplo en la parte del servidor no hay problemas. (Eso Creo...)

Cliente:
Para invocar al método definido en el servidor "UpdateDeltas" se pueden hacer de 2 maneras:

1. Usando el componente TSQLServerMethod que configurando la clase del servidor datasnap se tiene el componente listo para invocar al método.

OJO: Yo he configurado el componente pero no me está funcionando ya que si ven el código desde el cliente se envían 2 parámetros OLEVARIANT y el componente al momento de configurar los parámetros del método los pone como VARIANTs y ahí me sale errores que no soporta los parámetros. SI ALGUIEN CAPAZ PUEDE VER QUE PUEDE ESTAR PASANDO... no creo que los de embarcadero no hayan considerado los parámetros OLEVARIANTS para los métodos en DATASNAP.

2. Obteniendo las Clases del Servidor hacia el Cliente(El algunos foros lo conocen como las clases Proxis) y en este caso si me está permitiendo invocar el método definido en el servidor y poder ejecutarlo con los parámetros OLEVARIANTS. Cosa rara porque se supone que es lo mismo. Ahí espero sus comentarios.

Continuando después de definida la llamada al método del servidor se ha definido un procedimiento llamado: ApplyUpdates que ahí lo que está haciendo es preparar la lista de Deltas y Providers los cuales van a ser enviados al Servidor por el método definido en los puntos 1(Con Errores por resolver) ó 2.

El ejemplo que les comparto todo esta funcionando con la excepción de un procedimiento ReconcileDeltas que lo que hace es de todos los Deltas actualizados en el servidor actualizarlos en los ClientDataSets correspondientes. Ahí está saliendo el problema y muestra un error: “Mismatch in datapacket."

Espero no haberlos confundido, yo por mi parte sigo investigando cual puede ser la causa de los 2 problemas que se me han presentado tanto en usar el componente TSQLServerMethod con parámetros OLEVARIANTS y al momento de hacer RECONCILE de los Deltas actualizados en la Base Datos.

Capaz ya a alguien les haya pasado algo similar y de verdad resolver lo que pongo en el tema nos va ayudar bastante a minimizar las llamadas al servidor.

Saludos.
Archivos Adjuntos
Tipo de Archivo: zip DSXE3.zip (189,9 KB, 61 visitas)
__________________
Maniches
maniches@outlook.com
Responder Con Cita
  #2  
Antiguo 09-11-2012
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
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
Hola Manuel.

Disculpa que no respondiera antes a tus mensajes. Me parece bien que hayas abierto este nuevo hilo para tratar de resolver entre los compañeros las inquietudes que te aquejan.

Pero hay que ir por partes, porque es un tema amplio el que planteas. Además pienso que puedes no tener muy claros algunos conceptos. Decir también que mi experiencia con el nuevo DataSnap (Delphi 2009 en adelante) es todavía poca, pero a ver si podemos ayudar. Conmigo ten paciencia porque dispongo de poco tiempo para los próximos días. Por tu parte debes estar dispuesto a dedicar lo que sea necesario a comprender y poner en práctica todo lo que discurra aquí.

Creo conocer un poco la clase TClientDataSet, digamos que es el área donde me siento más seguro dentro de todo este terreno, pero hay compañeros que dominan mejor la práctica de montar sistemas multicapa con DataSnap. A estos los animo a aportar su conocimiento, porque seguro que no sólo a Maniches le servirá.

Analicemos el siguiente punto (evitemos los demás hasta que éste quede resuelto):

Cita:
Empezado por Maniches Ver Mensaje
[...] y que luego de haber actualizado la información en el motor de base datos estos Deltas se actualicen en los ClientdataSets del Cliente. Puede ser mediante RECONCILE o otro forma que se vea conveniente. [...] luego de hacer la actualización a la base datos viene otro problema ya que hay que refrescar el cache de los ClientDataSets por el lado del cliente, la forma sencilla seria refrescar cada dataset con Close/Open o Refresh, esto originaria ejecutar nuevamente las consultas por cada Dataset.
Primero aclarar que Delta es, como dice la ayuda de Delphi sobre la propiedad TClientDataSet.Delta: un paquete de datos del registro de cambios.
Cita:
Use Delta to pass a packet of change log data from the client dataset to a provider. Delta contains only information about those records inserted, modified, or deleted through the client.
En segundo lugar, debes saber que el método TClientDataSet.Reconcile tiene como propósito limpiar el registro de cambios del conjunto de datos después de que su Delta fue enviado al servidor con ApplyUpdates (para grabar todos los cambios en la base de datos), pero habiendo ocurrido impedimentos para guardar alguno(s) de esos cambios —como al intentar la inserción de un registro con la misma clave que otro—.

El mismo método ApplyUpdates se encarga de llamar a Reconcile cuando el servidor rechaza alguno de los cambios. Reconcile tiene varias formas de tratar con esos cambios rechazados, entre ellas disparar el evento OnReconcileError para que sea el programa (el programador de la aplicación) quien determine qué hacer (ignorar, corregir el campo en cuestión y reintentar, etcétera).

Reconcile y OnReconcileError no sirven para "refrescar" los registros que tiene en memoria el conjunto de datos cliente. No es ese su propósito.

Varios motores soportan la devolución de datos automática tras una inserción (Insert Into) o actualización (Update). Esto podría ayudarte a "refrescar" en memoria los cambios que adicionalmente el servidor haya realizado mediante disparadores Before Insert y Before Update, pero desconozco qué tan fácil sería montarlo sobre los mecanismos habituales de comunicación TDataSetProvider-TClientDataSet, además, también dependerá de la conexión que uses (ADO, dbExpress, IBX) y cómo ésta última soporte el "returning" de los Inserts y Updates en tu versión de Delphi (yo no he revisado).

Imagino que no ha de ser imposible canalizar esa devolución del servidor hasta la aplicación cliente, para que ésta actualice su "caché" de registros (TClientDataSets), ya que tanto TDataSetProvider como TClientDataSet posibilitan la transmisión de todo tipo de información.

Pero antes de intentar ese camino, considera que hay por lo menos otra forma en que un conjunto de datos cliente puede refrescar los registros que ha enviado al servidor, sin tener que hacer un completo Refresh o Close + Open. Consiste en consultar con un TClientDataSet auxiliar aquellos registros que nos interesan, y luego copiarlos al primer TClientDataSet. En este hilo se trató el tema. Creo que te puede servir.

Cierto, eso supone volver a hacer una consulta al Servidor, pero al menos no traes de él todos los registros que ya tienes en memoria, sino solamente los que acabas de mandar, reduciendo significativamente el peso de la solicitud.

Nos leemos pronto, saludos...

Al González.
Responder Con Cita
  #3  
Antiguo 10-11-2012
Avatar de Maniches
Maniches Maniches is offline
Miembro
 
Registrado: nov 2012
Ubicación: Lima - Perú
Posts: 67
Poder: 12
Maniches Va por buen camino
Lightbulb

Hola Amigo AL,
Muchas Gracias por tomarte un tiempo y por ser muy claro en tus respuestas.

Para iniciar mis comentarios voy a comentar parte por parte tu respuesta amigo AL, pero inciar comentando:

Cita:
El Caso que he comentado y he detallado se ha implementado en un compañía grande con bastante concurrencia de información. Por ello se implemento el tener que crear arreglos de Provider y Deltas y estos enviarlos al servidor en una sola transacción y que la actualización hacia el cliente sea transparente, utilizando los deltas enviados al servidor y que estos me permitan actualizar en cache de los ClientDataSet.
Les comentaba a los amigos que es muy importante esto ya que a cualquiera se le puede presentar módulos que impliquen muchas tablas anidadas y relacionadas como era el caso que expongo y se complicaba mas cuando tienes 1000 a 2000 usuarios ONLINE golpeando toda esa lista de tablas.

Cita:
Cuando implementamos la solución esta programado de la siguiente manera: Servidor(ADO Components, Providers) Cliente(DCOM, ClientDataSets, Datasource) Claro que esta arquitectura usa MIDAS, un poco preparándose y evitar la problemática de no tener soporte de DCOM en los nuevos Windows es que decidí hacer la migración de este método a DATASNAP con DXE3
Yo he avanzado gran parte de la migración por ello que he puesto un ejemplo en el HILO que les permita ver mejor a mas detalle lo que se esta comentando. Claro que el ejemplo esta con una sola tabla y si se resuelve ya lo demás es sencillo.

Aquí mis comentarios a tus respuestas amigo AL:

Cita:
Primero aclarar que Delta es, como dice la ayuda de Delphi sobre la propiedad TClientDataSet.Delta: un paquete de datos del registro de cambios...
Si amigo me referia al Delta del Cliente que este se envía al servidor para actualizar los cambios. ten presente que no se envía directamente desde el componente (TClientDataSet.Delta) se hace mediante un arreglo de Variants y todo el paquete es un OLEVariants.

Cita:
En segundo lugar, debes saber que el método TClientDataSet.Reconcile tiene como propósito limpiar el registro de cambios del conjunto de datos después de que su Delta fue enviado al servidor con ApplyUpdates...
Muy cierto lo que comentas con respecto a RECONCILE. eso es lo que se quiere hacer de las 10 a 20 tablas actualizadas limpiar los registros de cambios. An la arquitectura anterior mencionada lo soportaba sin problemas. En el ejemplo esta el método ReconcileDeltas que debería hacer eso y es el que trae problemas. Ya que como decía muestra el error: "Mismatch in datapacket."

Cita:
El mismo método ApplyUpdates se encarga de llamar a Reconcile cuando el servidor rechaza alguno de los cambios. Reconcile tiene varias formas de tratar con esos cambios...
Muy cierto tus comentarios, ya que los eventos que mencionas se ejecutan cuando hubo un problema en la actualización sino simplemente quita el registro de cambios.

Cita:
Reconcile y OnReconcileError no sirven para "refrescar" los registros que tiene en memoria el conjunto de datos cliente. No es ese su propósito...
Es verdad lo que mencionas. Pero como la actualización no se esta haciendo usando el método ApplyUpdate del componente ClientDataSet. es por ello que en el ejemplo lo esta haciendo después de haber actualizado en la base datos para quitar los registros de cambios de los CDS. El detalle que hay algo que no esta permitiendo que se pueda realizar el RECONCILE.

Cita:
Imagino que no ha de ser imposible canalizar esa devolución del servidor hasta la aplicación cliente, para que ésta actualice su "caché" de registros (TClientDataSets), ya que tanto TDataSetProvider como TClientDataSet posibilitan la transmisión de todo tipo de información...
El problema no se esta presentando cuando se hace directamente con los componentes. Ten presente que todo esta en Arreglos Variants y toda la información se envía como OLEVariants

Cita:
Pero antes de intentar ese camino, considera que hay por lo menos otra forma en que un conjunto de datos cliente puede refrescar los registros que ha enviado al servidor, sin tener que hacer un completo Refresh o Close + Open...
Es muy cierto que hay otras formas como lo mencionas, Voy a revisar el Hilo que me has compartido ahí te comento. Como se esta hablando que hay varios Datasets implicados el hacer otros caminos va a demandar mas trabajo y no necesariamente puede cubrir para la optimización que se desea.
Voy a hacer unas pruebas y les comento.

Cita:
Cierto, eso supone volver a hacer una consulta al Servidor, pero al menos no traes de él todos los registros que ya tienes en memoria, sino solamente los que acabas de mandar, reduciendo significativamente el peso de la solicitud...
Como les comentaba el metodo estaba funcionando bien, claro con otra arquitectura. Pero si no es soportado por DATASNAP. No me va a quedar otra que definir Datasets en paralelo con sus parametros correspondientes por PK y traer la lista de registros que tan solo han sido Insertado/Modificados/Eliminados eso ya seria como ultima alternativa y cuando ya me quede sin cabellos... jejeje una broma

Espero haya aclarado un poco mas mis comentarios y estamos comunicandonos amigo AL.

Amigos del Foro siempre es bueno recibir consejos, sugerencia y aportes de las amigos que capaz ya se hayan enfrentado a algo similar.

Saludos a Todos un buen fin de Semana.
__________________
Maniches
maniches@outlook.com
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
Conectar varias Bases de Datos con Server DataSnap gcaffe Providers 5 22-05-2016 02:55:09
DataSnap XE3 - Actualización masiva de datasets con datasnap server. Maniches Conexión con bases de datos 0 08-11-2012 08:11:39
DataSnap Server Remoto - Delphi XE mrh_peru Providers 4 30-10-2011 04:51:06
datasnap para sql server??? _CALI Conexión con bases de datos 5 25-04-2011 19:49:04
Actualizacion masiva con trigger lledesma SQL 1 23-04-2009 00:24:09


La franja horaria es GMT +2. Ahora son las 16:11:23.


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