Datacontrols: Manejo de errores

Tradicionalmente en xBase el control de errores en el manejo de bases de datos se ha realizado a priori, es decir, se evitaba que se produjese ningún error de ejecución y para ello se utilizaban funciones como RLock(), FLock() o NetErr(). RLock() y FLock() son funciones que permiten realizar actualizaciones cuando el fichero DBF no es abierto en modo exclusivo, y NetErr() permite comprobar basicamente si una operación USE o APPEND BLANK se ha producido correctamente. Lógicamente con Xailer puede seguir utilizando este mismo sistema.

Sin embargo, este enfoque tradicional de xBase de manejar errores resulta muy limitado cuando se empiezan a manejar otros tipos de bases de datos como puede ser cualquier base de datos SQL ya que entonces existen múltiples causas que pueden provocar que una actualización no termine correctamente, y en dicho caso el servidor SQL notifica del error cuando se intenta realizar la actualización y es imposible conocer a priori si la operación va a tener éxito.

Los Datacontrols de Xailer incorporan un complejo mecanismo de control de errores que permite conocer todos los errores producidos. A nivel de TDataSource incorpora los métodos IsError(), LastError(), DelErrors(), GetErrors() y ShowErrorList():

  • IsError() retorna verdadero si se ha producido algún error
  • LastError() retorna la descripción del último error producido
  • DelErrors() elimina del registro de errores todos los errores existentes
  • GetErrors() retorna en una matriz multi-dimensional todos los errores producidos
  • ShowErrorList() muestra una ventana con todos lo errores producidos

A nivel de TDataSet incorpora las siguientes propiedades de sólo lectura:

  • cLastError, con la descripción del último error producido
  • nLastError, con el número interno del último error producido

Y el método DelError() para borrar el último error producido. (disponible a partir de la versión 1.2b)

Para establecer la forma en la que se controlarán los errores la clase TDataSource ofrece dos propiedades:

  • lAbortOnErrors
  • lDisplayErrors

La primera propiedad lAbortOnErrors permite forzar un error de ejecución cuando se produzca cualquier error, siendo su valor por defecto falso. La segunda propiedad lDisplayErrors permite que se visualicen en pantalla todos los errores según se vayan produciendo, por defecto su valor es verdadero.

Según la configuración inicial que propone Xailer de estas dos propiedades la forma de realizar un control de errores se basaría en la consulta de las propiedades y métodos enumerados anteriormente. Por ejemplo:

oDataSet:Update()
IF oDataSet:nLastError != 0
   MsgInfo( "Error de actualización, proceso abortado." )
   oDataSet:DelError()
ENDIF

 

Como la propiedad lDisplayErrors está por defecto a verdadero Xailer le mostrará también una ventana cuando se produzcan los errores, por lo que es posible que prefiera mostrar un único mensaje poniendo está propiedad a falso y en el mensaje suyo incluir la información proporcionada por las propiedades cLastError y nLastError.

Observe como es necesario poner en blanco las propiedades cLastError y nLastError con el método DelError() para futuras actualizaciones.

Xailer propone otra técnica, a mi modo de ver, más cómoda para controlar los posibles errores, utilizando la propiedad lAbortOnErrors. Esta propiedad como hemos comentado provoca un error de ejecución cuando se produce cualquier error y es precisamente dicho mecanismo el que vamos a utilizar para controlar los errores. Para ello deberemos utilizar el clásico bloque TRY..CATCH..END existente en xHarbour para poder controlar el error:

TRY
   oDataSet:Update()
CATCH
   Msginfo( "Error de actualización, proceso abortado." + CRLF + oDataSet:cLastError )
END

 

Observe como a diferencia del sistema anterior no requiere hacer un borrado de los errores con el método DelError() y tampoco es necesario realizar múltiples sentencias tipo IF para controlar si se ha producido un error. Las mejoras de este sistema son mucho más evidentes cuando se hacen múltiples operaciones sobre el mismo TDataset:

TRY
   oDataSource:BeginTransaction()
   WITH OBJECT oDataSet
      DO WHILE !:Eof()
         :FastEdit()
         .........................
         :FastUpdate()
         :Skip()
      ENDDO
   END WITH
   oDataSource:CommitTrans()
CATCH
   oDataSource:RollBAckTrans()
   Msginfo( "Error de actualización, proceso abortado." + CRLF + oDataSet:cLastError )
END

 

Como ha podido ver la configuración inicial que le muestra Xailer en el DataSource de lAbortOnErrors a falso y lDisplayErrors a verdadero posiblemente no sea la más apropiada para su programa de gestión, sin embargo, entendemos que si es la apropiada durante la fase de diseño y sobre todo para aquellas personas que se inician en el uso de Xailer.

No obstante, incluso cuando la propiedad lDisplayErrors se encuentre a falso Xailer mostrará el error a través de la ventana de depuración. (sólo disponible a partir de la versión 1.2b)