18 de mayo de 2018

Buffering - Parte 2

Buffering Parte II


 

Buffering, El Vampiro Asesino, la historia continua

En el artículo anterior se pudo ver que con el bufer de datos activado, la modificación se realiza en una copia de los datos. La cuestión obvia es ¿Cómo hacer que dicha copia se actualice en la tabla?. Con la función TableUpdate.

Una definición ayudará con la discusión, bufer sucio. Un bufer sucio es un bufer de datos que contiene cambios pendientes que no han sido actualizados en la tabla.

Actualizar o no actualizar

TableUpdate es la función que provoca que los datos de un bufer se escriban sobre una tabla. Esta función tiene (4) argumentos, la sintaxis es,

TABLEUPDATE( [nFilas|lFilas> [, lForzar]] [, cAliasTabla | nÁreaTrabajo] [, cMatrizErrores])

Como se puede ver, todos los argumentos de esta función son opcionales. Realizando un TableUpdate sin argumentos actualizará el registro actual de la área de trabajo activa y no avisará de un conflicto de actualización. Vamos a ver los argumentos en detalle.

nFilas | lFilas

En Visual Foxpro 3.0 el primer argumento era lógico y .T. significaba que se debían actualizar todos los registros cambiados, mientras que .F. solo significaba que se actualizará el registro actual. Este argumento lógico todavía funciona en Visual FoxPro 6.0, pero la alternativa numérica nos da un mayor control sobre esto.

El argumento numérico puede ser 0, 1 o 2 y controla como se actualizan los registros. Un argumento de 0 (el valor por defecto) solo actualizará el registro actual. Usando 1 o 2 actualizará todos los registros modificados. La diferencia entre 1 y 2 tiene que ver en que sucede si uno o más de los registros modificados no pueden ser actualizados.

Poniendo 1originará que el tableupdate falle si cualquiera de los registros no puede ser actualizado. Mientras que con 2 forzará a que Visual FoxPro actualice todos los registros que pueda y que guarde una lista de los registros que no pueden ser actualizados (esta lista es almacenada en la matriz pasada como cuarto argumento).

lForzar

Este argumento, de tipo lógico, controla si Visual FoxPro dará un fallo en el TableUpdate si el registro que está siendo actualizado ha sido cambiado por otro usuario mientras estabamos realizando las modificaciones. Un valor de .T. fuerza la actualización aunque haya un conflicto, mientras que .F. provocará que la actualización falle si el registro del disco no está igual que como estaba al principio de las modificaciones.

Recomiendo encarecidamente que este argumento esté siempre a .F.. La razón es que si no lo haces, tu código puede reemplazar las modificaciones de otros usuarios indiscriminadamente. Lo que realmente debes hacer es controlar el valor de retorno del TableUpdate para ver si se ha realizado correctamente o no, y responder en este caso.

cAliasTabla | nÁreaTrabajo

Este argumento es el nombre del área de trabajo al cual le afecta el tableupdate. Puede ser o bien el alias ó el número del área de trabajo (¿Sigue alguien usando números de áreas de trabajo en su código?).

Este es otro de los argumentos opcionales que es recomendado usar siempre. Si se omite este argumento entonces el TableUpdate afectará solo al área de trabajo activa. Como podemos controlar esta situación, es recomendable que le digamos al TableUpdate a que área de trabajo debe afectar y no depender que el área de trabajo haya sido correctamente seleccionada. La razón es que Visual FoxPro está orientado a eventos y puede llegar a suceder que no seas capaz de saber cual es el área de trabajo activa debido a que diversos eventos pueden cambiar el área de trabajo activa. Poniendo el alias en la función TableUpdate eliminarás cualquier posible efecto de equivocarte en el área de trabajo a actualizar.

cMatrizErrores

Este último argumento solo es válido si el primer argumento es 2. Con el primer argumento puesto a 2, la función TableUpdate intentará actualizar todos los registros modificados y si alguno falla se pondrá el número de registro que ha fallado en la matriz cMatrizErrores.

 

Un ejemplo de valores 1 y 2 como primer argumento pueden ayudar a saber que significa todo esto. Vamos a suponer que los registros 1, 3, 5, 6 y 9 han sido modificados en un bufer por tablas. Realizamos un TableUpdate con 1 ó 2 como primer argumento y hay un conflicto de actualización en los registros 3 y 6.

Con un valor de 1 en el primer argumento, la función TableUpdate actualizará el registro 1 y entonces cuando no pueda actualizar el registro 3 parará de intentar actualizar registros y devolverá un .F. indicando un fallo de la operación de actualización. Usar el valor 2 como primer argumento, provocará que la función TableUpdate continúe intentando actualizar el resto de los registros después de que fallara el registro 3. La matriz definida en el cuarto argumento mantendrá la lista de registros que no han podido ser actualizados (3 y 6), el TableUpdate de todos modos devolverá .F. indicando un fallo en la actualización debido a que no se ha completado dicha actualización.

…No Actualizar

Utilizar el almacenamiento de datos en bufer no solo nos permite guardar las modificaciones que ha realizado un usuario, también ofrece un método para descartar las modificaciones. La función TableRevert restaurará un bufer sucio poniendo los valores como estaban almacenados anteriormente en el disco, la sintaxis es la siguiente;

TABLEREVERT([lTodasFilas [, cAliasTabla | nÁreaTrabajo]])

Los dos argumentos de esta función son descritos en las siguientes secciones.

lTodasFilas

Este argumento, de tipo lógico, controla que registros serán restaurados, si es .T. entonces todos los registros sucios serán restaurados en el alias seleccionado, un valor de .F., solo restaurará el registro actual. Si no se especifica este argumento solo afectará al registro actual.

cAliasTabla | nÁreaTrabajo

Es el nombre de alias o número de área de trabajo sobre la cual la función TableRevert actúa. Si no se especifica se hará sobre el área de trabajo activa.

¿Cómo es el vampiro asesino?

Las funciones TableUpdate y TableRevert devuelven valores que indican si han sido realizadas correctamente o con fallos. TableUpdate devuelve un valor lógico .T. indicando que la actualización ha sido completada satisfactoriamente o una valor .F. indicando que la actualización ha fallado en parte o completamente. TableRevert devuelve un número que indica el número de registros que han sido restaurados.

En ambos casos es importante conocer los valores devueltos y reaccionar a ellos. Por ejemplo, el siguiente código podría ser usado para actualizar un bufer de la tabla clientes.

IF NOT TableUpdate(1,.F.,”Clientes”)

   Wait Window “Imposible grabar su trabajo”

   TableRevert(.T.,”Clientes”)

ENDIF

La sentencia IF comprueba el valor devuelto por el TableUpdate y actúa en consecuencia. El TableRevert es necesario porque un TableUpdate que falle no actualiza la tabla, pero deja el bufer sucio y este debe ser limpiado antes de cerrar la tabla. Hay otras maneras de controlar fallos del TableUpdate, por ejemplo;

IF NOT TableUpdate(1,.F.,”Clientes”)

  IF MessageBox(“Imposible grabar su trabajo. ¿Quieres descartar los cambios?”,;

                 MB_YESNO,”Actualización fallida”) = IDYES

    TableRevert(.T.,”Clientes”)

  ENDIF

ENDIF

En este caso el fallo del tableupdate originará que el usuario reciba un message box preguntándole si desea descartar los cambios. Si se escoge "si" entonces la tabla es restaurada, si no se mantendrá en el formulario manteniendo sus cambios intactos. El usuario podrá intentar guardar los cambios mas tarde.

Téngase en cuenta en ambos ejemplos que no se ha puesto una selección del área de trabajo. Esto es debido a que el área de trabajo es especificada en las funciones y así no hay necesidad de seleccionar ningún área de trabajo en particular.

Resumen

En el ultimo artículo hemos revisado el sistema de almacenamiento de tablas en bufer a grandes rasgos y descubrimos lo que puede hacer por nosotros. Vimos que el almacenamiento en bufer puede hacer que nuestro código sea mas simple y fácil de entender

En este artículo han sido revisadas las dos principales funciones que afectan al almacenamiento en bufer, TableUpdate() y TableRevert(). Estas dos funciones nos dan un control definitivo acerca de si las modificaciones en el bufer serán escritas en el disco y cuando serán realizadas.

 

No hay comentarios. :

Publicar un comentario

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.