Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Danysoft Internacional Avda de Espaa 17 28100 Alcobendas Madrid Tfno. 902.123146 Fax. 902.123145 http://www.danysoft.com http://www.danyshop.com danysoft@danysoft.com
-1 0 1
3 3 3
1y3 2 2
En la segunda entrega vimos la secuencia de eventos que genera el DataSetProvider durante el proceso de actualizacin. Cuando ocurre un error al intentar actualizar un registro el DataSetProvider genera el evento OnUpdateError, en el que recibimos informacin detallada acerca del error ocurrido, el registro que gener el error y el tipo de actualizacin que se intent realizar. En este evento podemos indicarle al DataSetProvider la accin que queremos que lleve a cabo con el registro en cuestin. Dependiendo del valor pasado a ApplyUpdates, el DataSetProvider continuar con el proceso de actualizacin o lo cancelar. Cuando ocurre un error de actualizacin el DataSetProvider finaliza la transaccin actual deshaciendo los cambios realizados, es decir, la finaliza haciendo Rollback. Debido a que las relaciones maestro/detalle son actualizadas en el contexto de la misma transaccin, si, por ejemplo, ocurre un error al actualizar un registro del detalle, los cambios al maestro sern cancelados. Sin embargo, si en el registro de cambios hay varios registros del maestro con sus correspondientes detalles, los registros actualizados correctamente no sern cancelados ya que fueron actualizados en el contexto de otra transaccin. Reconciliacin de errores de actualizacin Al finalizar el proceso de actualizacin, ya sea porque se comp let o porque finaliz debido a que se super la cantidad mxima de errores de actualizacin tolerados, el DataSetProvider le informa al ClientDataSet lo ocurrido. Para cada registro hay tres situaciones posibles: que el registro haya sido actualizado, que el registro no haya sido actualizado debido a un error de actualizacin o que el registro no haya sido actualizado porque el proceso de actualizacin finaliz antes de intentar actualizarlo. A continuacin se describe lo que ocurre en cada caso: Los registros que fueron actualizados son quitados del registro de cambios y mezclados con los registros originales. Para cada uno de los registros que no fueron actualizados debido a un error de actualizacin, el ClientDataSet genera el evento OnReconcileError. En este evento recibimos informacin detallada acerca del error ocurrido, el registro que gener el error y el tipo de actualizacin que se intent realizar. Aqu tambin podemos indicarle al ClientDataSet la accin que queremos que lleve a cabo con el registro en cuestin. Es importante escribir un manejador para este evento ya que de lo contrario corremos el riesgo de no enterarnos si han ocurrido errores de actualizacin. Esto se debe a que el ClientDataSet no genera excepciones por errores de actualizaci n. Los registros que no fueron actualizados porque el proceso de actualizacin finaliz antes de intentar actualizarlos, son mantenidos en el registro de cambios. Para estos registros no se genera ningn evento. El mtodo ApplyUpdates devuelve un valor entero que indica la cantidad de errores de actualizacin ocurridos. Por ejemplo, el valor 0 indica que no hubo errores de actualizacin. En lugar de escribir un manejador para el evento OnReconcileError podemos evaluar el valor devuelto por ApplyUpdates para saber si ocurrieron errores de actualizacin. Para reconciliar los errores de actualizacin Borland provee la unidad RecError, conteniendo la funcin HandleReconcileError, que le presenta al usuario un
www.danysoft.com - Pgina 4/7
formulario con informacin del error y la posibilidad de realizar acciones correctivas para intentar actualizar nuevamente el registro que gener el error.
La imagen de arriba muestra el formulario presentado por la funcin HandleReconcileError para el caso de un registro que no pudo ser actualizado debido a un problema de concurrencia. En este caso, el usuario intent modificar el campo OnOrder de la tabla Parts del alias DBDemos pero otro usuario modific el mismo registro asignndole otro valor a dicho campo. El ClientDataSet nos permite acceder al valor ingresado por el usuario (propiedad Value), el valor original obtenido por el usuario (propiedad OldValue) y el valor actual en la base de datos (propiedad CurrValue). El idioma original de este formulario es ingls pero el cdigo fuente est disponible en el directorio de la VCL por lo que podemos modificarlo para traducirlo, por ejemplo, al castellano. En todos los casos, los registros que no fueron actualizados permanecen en el registro de cambios tal y como los modific el usuario. Esto es muy importante ya que significa que el usuario no pierde las modificaciones realizadas y que puede realizar acciones correctivas para intentar solucionar el problema que gener el error de actualizacin. Por ejemplo, supongamos que el usuario ha ingresado una orden con 40 tems y la cantidad de stock disponible para el producto del ltimo tem no es suficiente para satisfacer el pedido. El usuario no slo no pierde todos los datos de la orden sino que podemos informarle la cantidad disponible para que modifique el tem nmero 40 para que la orden pueda ser procesada. Transacciones y actualizaciones encadenadas Los eventos del DataSetProvider nos permiten encadenar actualizaciones como si estuviramos utilizando disparadores en una base de datos SQL. Por ejemplo, en el evento BeforeUpdateRecord generado antes de actualizar cada tem de una orden, podemos escribir cdigo para actualizar el stock del producto. Este cdigo podra estar contenido en el Data Module de lgica de datos de productos y utilizar un
ClientDataSet y un DataSetProvider para acceder a un producto en particular. No sera necesario repetir este cdigo en el mencionado evento. Todo lo que tenemos que hacer es llamar al mtodo apropiado en el Data Module de lgica de datos de productos. En este Data Module, el DataSetProvider de productos, al momento de actualizar el stock de un producto, no iniciar una nueva transaccin porque detectar que ya existe una transaccin iniciada (el DataSetProvider de rdenes la inici) por lo que slo se limitar a actualizar la tabla de productos. Es ms, como el DataSetProvider de productos no inici la transaccin tampoco la finalizar. En este esquema es fundamental generar una excepcin si ocurre un error al actualizar la tabla de productos. De esta forma el DataSetProvider de rdenes, al capturar la excepcin, podr finalizar la transaccin actual cancelando los cambios realizados. Estas caractersticas del DataSetProvider nos permiten encapsular la lgica de productos en el Data Module de productos; la lgica de rdenes en el Data Module de rdenes y as sucesivamente. De esta forma la aplicacin ser ms fcil de modificar y tendremos ms posibilidades de reutilizar cdigo. Por ejemplo, si por algn motivo debemos modificar el proceso de actualizacin del stock de productos, slo tendremos que hacer cambios en el Data Module de lgica de datos de productos. Actualizaciones en cascada El DataSetProvider soporta el uso de actualizaciones en cascada para la eliminacin y modificacin de registros en relaciones maestro/detalle. Este soporte est pensado para aquellos casos en los cuales, por ejemplo, la eliminacin de una orden est completamente resuelta en la base de datos. Es decir, aquellos casos en los que slo tenemos que eliminar el registro maestro ya que en la base de datos, por medio de disparadores, los registros del detalle sern eliminados automticamente. En estos casos, el DataSetProvider slo deber generar sentencias SQL de DELETE para el registro maestro. Por medio de la propiedad Options del DataSetProvider podemos indicar si dicho DataSetProvider soporta eliminaciones y actualizaciones en cascada. En el ClientDataSet, cuando el DataSetProvider soporta eliminaciones en cascada, podemos eliminar un registro del maestro aun cuando existan registros en el detalle. Esto es as porque el DataSetProvider asume que la base de datos se encargar de eliminar los registros del detalle. Hay que tener mucho cuidado con las eliminaciones y actualizaciones en cascada ya que el DataSetProvider no generar sentencias SQL para eliminar o actualizar los registros del detalle y, por lo tanto, no generar los eventos BeforeUpdateRecord y AfterUpdateRecord para los registros del detalle. Si la lgica de datos de nuestra aplicacin utiliza estos eventos para los registros del detalle entonces no deberamos habilitar eliminaciones y actualizaciones en cascada. La nica limitacin ser que no podremos eliminar un registro del maestro si existen registros en el detalle. Esta limitacin puede ser fcilmente resuelta si antes de eliminar un registro del maestro eliminamos todos los registros del detalle. Conclusiones La reconciliacin de errores de actualizacin es un tema muy importante que pocas veces consideramos como es debido. Los errores de actualizacin pueden significar una experiencia frustrante para los usuarios de nuestra aplicacin. El esfuerzo dedicado a que este proceso sea lo ms amigable posible ser muy bienvenido por ellos y nos ahorrarn muchas llamadas de soporte.
www.danysoft.com - Pgina 6/7
El mecanismo ofrecido por Borland puede ser suficiente en la mayora de los casos, pero si necesitamos modificarlos tenemos todas las herramientas para hacerlo. El formulario contenido en la unidad RecError es una fuente de aprendizaje invalorable, como la mayor parte del cdigo fuente de la VCL. Analizando el cdigo fuente de esta unidad podemos aprender mucho y ajustar a nuestras necesidades el mecanismo ofrecido por Borland. Otro concepto fundamente es la encapsulacin. La gestin de transacciones del DataSetProvider nos permite anidar actualizaciones como si se tratara de disparadores. Esto nos da la posibilidad de encapsular la lgica de datos en distintos Data Modules y hacer que nuestras aplicaciones sean ms fciles de actualizar y mejorar las posibilidad de reutilizar cdigo.