Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   TClientDataSet.ImmediateUpdates (https://www.clubdelphi.com/foros/showthread.php?t=30633)

Al González 12-04-2006 00:53:34

TClientDataSet.ImmediateUpdates
 
¡Hola a todos!

¿A poco no sería fabuloso que el componente TClientDataSet tuviese una propiedad llamada ImmediateUpdates, para indicar cuándo queremos que se apliquen los cambios (ApplyUpdates) a la base de datos de manera inmediata?.

Muchos programadores Delphi recurrimos al uso de los eventos AfterPost y AfterDelete del conjunto de datos cliente, para llamar desde ahí al método ApplyUpdates cuando queremos que la base de datos se actualice immediatamente después de guardar o eliminar un registro. Pero cuando tenemos un módulo de datos con treinta o cuarenta componentes TClientDataSet la cosa se torna fea (demasiado trabajo repetitivo por falta de una propiedad como la mencionada).

Hace días que vengo utilizando mi propio componente derivado: TMagiaClientDataSet, al cual le voy agregando características según descubro las carencias de su clase padre (TClientDataSet). Le definí una propiedad Provider que permite enlazarlo con un proveedor que se encuentre en otro módulo de datos de la misma aplicación; también una propiedad StoreActive que evita (si se quiere) que se guarde la propiedad Active en el archivo .dfm.

Ahora he decidido definirle una nueva propiedad llamada ImmediateUpdates. La idea es sencilla: que si esta propiedad tiene un valor de True, se llame de manera automática al método ApplyUpdates después de cada operación de guardado o eliminación de registro. Eso ayudaría a reducir código y trabajo de programación operativa (el burocrático uso de los eventos AfterPost y AfterDelete de cada conjunto de datos).

La principal razón de este mensaje es preguntar a los conocedores del tema, cuál valor debería ser el predeterminado (default) para esta nueva propiedad, ¿True o False?. En términos prácticos, ¿cuál se estaría usando más por los programadores Delphi que emplearan este nuevo componente?, ¿ImmediateUpdates = False?, o ¿ImmediateUpdates = True?, ¿por qué?

Muchas gracias por participar en la encuesta y exponer sus opiniones sobre este tema.

Un abrazo aplicado.

Al González. :)

jmariano 12-04-2006 01:51:58

He votado True porque en todos los programas en los que he participado en su desarrollo siempre aplicamos la "actualización" inmediatamente después de que se produce una edición/inserción o eliminación.

Además, opino que, salvo que permitamos el trabajo en modo "briefcase", es peligroso posponer mucho la actualización hacia la base de datos debido a los problemas que puedan ocurrir (corte de corriente, cuelgue del sistema operativo, etc.), en cuyo caso se perderían todas las modificaciones hechas al estar sólo en la "cache" (y hablo por experiencia, imaginad como explicarle al cliente que las últimas modificaciones hechas se perdieron porque "se fué la luz!").

En fín, a ver que opináis los demás...

Saludos!

P.D: Sólo decir que me parece muy buena idea lo de adaptar el TClientDataSet, nunca se me ocurrió "personalizarlo" sino que más bien me las rebuscaba para intentar que todo funcionara correctamente.

roman 12-04-2006 02:32:55

Pues yo he votado false. No es que considere mala idea hacer esto en automático pero sí pienso que hay que andarse con tiento. Difícilmente consideraría esto como una carencia del TClientDataSet original. Me parece que el uso de ApplyUpdates es parte clave del diseño, encaminado a la disminución del tráfico en la red, no sólo un paso extra para hacernos programar más. Quizá el uso de ApplyUpdates es más algo a lo que haya que acostumbrarse como parte de una filosofía de programación, más una regla que una excepción y por ello false por defecto que no true.

Lo que me parece genial es el la propiedad StoreActive. ¡Cuántos dolores de cabeza no da el dejar esta propiedad activa durante el diseño! Creo que ninguna componente derivada de DataSet debió dejar siquiera la opción de poder almacenar esto en el dfm.

// Saludos

Casimiro Notevi 12-04-2006 08:16:10

false, por los motivos que explica roman.
Lo de storeactive: genial, se evitan muchos quebraderos de cabeza. Bueno, coincido por completo con roman :)

amadis 13-04-2006 00:13:09

True
 
VOTO POR EL TRUE.

Ya que hace unos dias publique un hilo CLIENTDATASET vs TTABLE

Y eso creo que solucionaria el problema que he estado teniendo... de reflejar los cambios inmediatamente.

El que no lo quiere que siga con el ClientDataSet tradicional

Ahora una cuestion este InmediateUpdates ¿seria un ApplyUpdate y un refresh juntos?

Ya que yo he estado usando esa combinacion en el AfterPost y AfterDelete y otros after y con el crecimiento de la tabla se torna muy lento el refresh al punto que es inaguantable.

En cuanto al StoreActive desconozco su utilidad y buscando en la ayuda de delphi no entendí mucho mas de lo que desconozco así que les agradeceria una ayuda sobre eso.

Al González 13-04-2006 21:40:59

ImmediateUpdates y StoreActive
 
¡Hola a todos!

Antes que nada, gracias por sus valiosos comentarios.


Cita:

Empezado por amadis
VOTO POR EL TRUE.

Ya que hace unos dias publique un hilo CLIENTDATASET vs TTABLE

Y eso creo que solucionaria el problema que he estado teniendo... de reflejar los cambios inmediatamente.

El que no lo quiere que siga con el ClientDataSet tradicional
...

He decidido que el valor predeterminado sea False (ya voté por la primera opción). Abrí la encuesta porque tenía dudas al respecto, pero me convenció el argumento de Román. La intención de este nuevo componente es ampliar las capacidades de un TClientDataSet, no pelearse con éste. La naturaleza de un conjunto de datos cliente es permitir el manejo de registros en memoria (en caché), aplicando los cambios a la base de datos hasta llegar el momento "adecuado", reduciendo así el tráfico de red.

En mi proyecto actual tengo un módulo de datos con varias decenas de este nuevo componente y, por razones particulares de esta aplicación, pondré la propiedad ImmediateUpdates de todos ellos en True (es un trabajo menor, comparado con el de utilizar los eventos AfterDelete y AfterPost de cada componente). Es muy probable que yo mismo y otros programadores hagan esto en otros proyectos, ya que muchos desarrolladores Delphi preferimos que los cambios se envíen a la base de datos lo más pronto posible (por todas las ventajas de lectura, validación, etc., que ya conocemos). Sin embargo, esta manera de usar la propiedad ImmediateUpdates, aunque puede llegar a ser una "regla cultural", sigue siendo una "excepción natural" (excepción a la naturaleza de un conjunto de datos en memoria).

En todo caso, para facilitar aún más el trabajo, quizá después cree una clase de módulo de datos que tenga una propiedad DefaultDataSetSettings —o un componente por el estilo—, donde el programador pueda establecer de forma centralizada cuáles son sus preferencias predeterminadas para todos conjuntos de datos que se coloquen dentro del módulo.


Cita:

Empezado por amadis
...este ImmediateUpdates ¿seria un ApplyUpdates y un Refresh juntos?...

No, solamente la llamada al método ApplyUpdates.
Código Delphi [-]
  Procedure TMagiaClientDataSet.DoAfterDelete;
  Begin
    If ImmediateUpdates Then
      ApplyUpdates (0);

    Inherited DoAfterDelete;
  End;

  Procedure TMagiaClientDataSet.DoAfterPost;
  Begin
    If ImmediateUpdates Then
      ApplyUpdates (0);

    Inherited DoAfterPost;
  End;


Cita:

Empezado por amadis
...En cuanto al StoreActive desconozco su utilidad y buscando en la ayuda de delphi no entendí mucho mas de lo que desconozco así que les agradeceria una ayuda sobre eso...

Cuando tienes StoreActive en False (el valor predeterminado), el valor de la propiedad Active no se guardará en el archivo .dfm, el archivo donde se almacena todo lo que estableces en tiempo de diseño —generalmente usando el inspector de objetos—. Esto quiere decir que si abres un conjunto de datos en tiempo de diseño para facilitar la labor de delinear un DBGrid, por ejemplo, enseguida puedes compilar el programa y al correrlo no abrirá automáticamente ese conjunto de datos; la tendencia hoy en día (y lo que señalan los cánones) es que el programa abra los conjuntos de datos por orden explícita, sólo en el momento en que se requieran, para ahorrar recursos y operar con una velocidad óptima.

Así mismo, cuando vuelvas a abrir el proyecto en Delphi, los módulos de datos no demorarán en cargarse, ya que no tratarán de abrir los conjuntos de datos que hayas dejado con las propiedades Active en True y StoreActive en False. En pocas palabras, StoreActive concilia la tendencia de conjuntos de datos cerrados con la necesidad de abrirlos para diseñar.


Un abrazo activo.

Al González. :)

Delfino 14-04-2006 20:03:11

Cita:

Pero cuando tenemos un módulo de datos con treinta o cuarenta componentes TClientDataSet la cosa se torna fea
pones el codigo siguiente para un solo CDS y con el Object Inspector lo ligas a los otros 30 o 40..

Código Delphi [-]
TClientDataset(DataSet).ApplyUpdates(0);

Al González 14-04-2006 21:23:50

Manejadores de eventos compartidos
 
¡Hola a todos!

Cita:

Empezado por Delfino
pones el codigo siguiente para un solo CDS y con el Object Inspector lo ligas a los otros 30 o 40..

Código Delphi [-]
TClientDataset(DataSet).ApplyUpdates(0);

Gracias por la observación Delfino. Eso es lo que se conoce como manejadores de eventos compartidos, pero no deja de ser una tarea que hay que hacer con varios eventos de muchos componentes (aún con la facilidad de seleccionarlos todos a la vez); es más cómodo y seguro para el programador trabajar con propiedades. Por otra parte, uno de los mayores inconvenientes de los manejadores de eventos compartidos ocurre cuando necesitamos utilizar alguno de los eventos en cuestión para realizar tareas adicionales que están relacionadas con un componente en particular, es decir, añadir código que ya no es aplicable a todos los componentes que comparten el manejador.

Me gustaría puntualizar que uso y recomiendo el uso de los manejadores de eventos compartidos en muchas situaciones —los utilizo desde Delphi 1 para ahorrarme muchas líneas de código—. No obstante, si existe una forma de escribir aún menos código sin sacrificar la eficiencia, debe ser bienvenida, máxime si se trata de soluciones orientadas a objetos.

Un abrazo compartido.

Al González. :)

roman 15-04-2006 04:27:28

Cita:

Empezado por Al González
la tendencia hoy en día (y lo que señalan los cánones) es que el programa abra los conjuntos de datos por orden explícita, sólo en el momento en que se requieran, para ahorrar recursos y operar con una velocidad óptima.

Además de esta razón yo veo otra que suele darme dolores de cabeza. Si abres explícitamente un dataset puedes usar un bloque try-except para manejar los posibles errores (el servidor está apagado, por ejemplo). Por otro lado, si la propiedad Active del dataset queda en true durante el diseño, la aplicación intentará abrirlo implícitamente desde el inicio sin darnos oportunidad de manejar adecuadamente la excepción.

// Saludos

roman 15-04-2006 04:31:32

Cita:

Empezado por Al González
muchos desarrolladores Delphi preferimos que los cambios se envíen a la base de datos lo más pronto posible (por todas las ventajas de lectura, validación, etc., que ya conocemos).

¿Podrías dar algunos ejemplos?

// Saludos

Al González 15-04-2006 20:05:02

Ejemplos
 
¡Hola a todos!


Cita:

Empezado por roman
¿Podrías dar algunos ejemplos?...

Claro, mi estimado Román. Aparte del buen ejemplo dado por el moderador Jmariano en el segundo mensaje, me gustaría decir que otra ventaja es poder advertir al usuario de alguna inconsistencia en la captura de datos desde el momento en que éste intenta guardar el primer registro erróneo y antes de que comience a capturar más registros con la misma inconsistencia. Es decir, poniéndome en los zapatos del usuario, preferiría que la aplicación me dijese (con palabras más formales desde luego) «no puedo guardar tu registro porque el monto dado es superior al permitido de $80.25» a «¿Qué crees? En catorce de los diecisiete registros que capturaste el monto es superior al permitido de $80.25» (considerando que el monto máximo puede variar de vez en cuando y es determinado por el servidor de la base de datos).

Deja tú (localismo), la cosa se hace más compleja cuando la validez de un dato de captura depende de condiciones dadas tanto por registros ya guardados en la base de datos, como por los que aún tenemos en el caché (evitar repetir claves únicas al capturar catálogos, por ejemplo), o cuando son varios los tipos de inconsistencias encontradas en el lote de registros enviados a la base de datos.


Entiendo que el modo caché también tiene sus ventajas, no descarto su utilización, pero de momento encuentro muy útil el ApplyUpdates inmediato.

Un abrazo validado.

Al González. :)


La franja horaria es GMT +2. Ahora son las 10:06:05.

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