Por curiosidad, ya que hablamos de AdoExpres y Datasnap, vamos a perder unos minutos en un par de comentarios que me parecen interesantes y que me hicieron reflexionar durante varios días de la semana anterior. Como muchos de los comentarios que hemos compartido, han surgido a raiz del trabajo diario. En este caso, concretamente al modificar la ficha de Clientes.

Estaba frente al típico esquema maestro-detalle donde el maestro era la tabla de clientes y los detalles eran cualquier otra tabla relacionada con ésta a través de una clave ajena. Una de estas tablas, mostraba en un dbGrid las comisiones que habían generado las ventas a determinado cliente, y en el interior de la pestaña que contenia la rejilla, existía un botón para recalcularlas y corregir errores generados en la modificación de las facturas. Resumiendo un poco, el proceso iba a disparar un procedimiento en la base de datos cuya misión era recalcular las comisiones que se mostraban en la rejilla y, en principio, no iba a retornar un conjunto de datos sino unicamente el exito en la finalización o el codigo del error de existir éste. Esto era problematico en el sentido de que, dado que nuestro conjunto de datos se ubica en la cache local y el procedimiento es disparado en nuestro servidor, los valores visualizados por el usuario podian en determinados casos diferir de los reales tras la ejecución del proceso, y podríamos necesitar invalidar el contenido de aquel dataset para mostrar los nuevos datos.

Además, si estamos en esos momentos en el contexto de nuestra aplicación, será habitual que el usuario se encuentre frente a una ventana modal (la ficha del cliente) que actualiza los cambios tras “aceptar” (que finalmente cerrará la ventana modal y actualizará los cambios pendientes). Ese esquema que parece el mas habitual y funciona bien en la mayoría de los casos, nos pone en una tesitura un tanto peculiar y problemática. O bien obligamos a nuestro usuario a confirmar cambios cerrando la ventana modal para que visualice los nuevos datos, lo cual no deja de ser una pequeña chapuza. O bien, creamos un datasets auxiliar que nos permitirá importar los registros que han cambiado y que añadiremos a la cache local, bien actualizando los existentes, bien insertando si fueran nuevos. Esta ultima opción es trabajo extra que a nadie le apetece hacer, sobretodo si consideramos la enorme cantidad de tablas que se implican en una aplicación normal y corriente (las que se utilizan en los ejemplos de los libros no tienen parecido alguno con las del mundo real) 🙂

En estos casos, lo habitual es acceder a Internet con el fin de comprobar si alguien ha tenido una inquietud similar y ha comentado algo al respecto. Y así lo hice. Y encontré casualmente un post en el foro del Club Delphi donde se comentaba este problema.

http://www.clubdelphi.com/foros/showthread.php?p=330090

En dicho post, participaba un programador de México, Al Gonzalez, que hace poco ha compartido algunos comentarios con nosotros, precisamente cuando hablabamos de Datasnap. El codigo final que se muestra en dicho post corrobora un poco lo comentado en las lineas anteriores.

Veamos un fragmento de dicho post:

procedure TForm1.Button12Click(Sender: TObject);
Var
  xClave:Integer;
begin
   //asegurase de que no existan pendientes
   //ya que MergeChangeLog lo eliminaria del Delta
    if ClientDataset3.ChangeCount>0 then
       showmessage('Hay datos pendientes en caché, aplicarlos antes del refresh')
    else begin
       //salvo el contenido del campo clave del registro a refrescar
       xClave:=ClientDataset3fcod_mast.AsInteger;
       //Leer de la Base de datos el registro a refrescar
       CDS_refresh.Close;
       CDS_refresh.Params.ParamByName('xClave').AsInteger:=xClave;
       CDS_refresh.Open;
       //borrar el registro que deseo refrescar
       ClientDataset3.Delete;
       //borrar datos de Delta
       ClientDataset3.MergeChangeLog; 
       // añadir el registro - RefreshRecord
       ClientDataset3.AppendData (CDS_refresh.Data, True);
    end;
end;

Aparte de estos comentarios, y los que pude leer repasando los cursos de Marteens sobre [AdoExpress/DBExpress] y DataSnap (o bien lo escrito por el autor en las distintas versiones de “La cara oculta de…”), el resto de información no es demasiado abundante ni clara. Marteens es una excepción en ese escenario ya que no conozco todavía a nadie que le haya leido y que piense que la compra de ese libro o ese curso ha sido un gasto inutil. Todo lo contario. Un problema que tenemos, in eternis, es el de que resulta facil encontrar textos que describen nuestras herramientas pero que dificilmente nos enseñan a usarlas en el mundo real. En el simil del martillo, encontrariamos cien mil textos que nos explicarian el origen del martillo en la historia de la humanidad. Doble cantidad hablando de forma elocuente sobre las distintas formas del mango. Y contados escritos (se podrían contar con los dedos de la mano) explicando como clavar un clavo sin machacarse los dedos. 🙂

Vamos a montarnos un pequeño ejemplo que nos permitirá experimentar y extrapolar el problema que hemos comentado. Imaginemos tres tablas, Articulos, Componentes y Composicion. Las relaciones entre ellas son muy sencillas. Lo mejor es verlo con una imagen.

relaciones

Es decir, la tabla Composición muestra una relación entre un articulo y los componentes de los que está compuesto.

Podéis descargar este zip que contiene el código fuente del ejemplo y un script para generar la base de datos en sqlserver:Fuentes

Ejecutamos el programa y seguimos comentando. Esto nos muestra la ventana principal.

experimento

El primer comentario o duda que nos puede asaltar es preguntarnos si no es posible actualizar un registro detalle de un forma limpia y sencilla. Ejecutad la aplicación. Luego editad cualquier campo y confirmad con un post, (por ejemplo la descripción del componente en la ficha del componente y en lugar del texto “Componente 1” poneis “Componente 1 modificado” o cualquier cosa que se os ocurra. Y finalmente, tras editar, pulsais el boton “Incrementa Cantidad” que ejecutará el procedimiento en el servidor que actualizará el campo cantidad en 10 unidades de cada uno de los componentes que forman parte de cada articulo. Es entonces cuando nos encontraremos el “problema”. Los registros de la tabla Composición han sido modificados por el usuario en un segundo plano pero el contenido de la rejilla no puede ser actualizado a menos que ejecutemos un ApplyUpdates. Solo entonces, es posible refrescar los datos.

Y no perdais de vista que nuestra ventana pueda ser modal, que puede ser una dificultad adicional con la que quizás tengamos que lidiar, por las razones comentadas al principio.

Vamos a hacer un pequeño alto en el camino, nos damos un pequeño respiro en este punto en el que ya tenemos planteada la inquietud. Os invito a seguir reflexionando sobre este tema en la siguiente entrada.

Un comentario sobre “Por curiosidad (Parte I)

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s