Transacciones sobre Access
Ha pasado mucho tiempo, muchas cosas y mucha funcionalidad desde la última publicación, cuando pueda intentaré hacer un resumen de la funcionalidad que lleva Nibi.Negocio actualmente. Pero voy a ir retomando la costumbre de escribir aquí con un tema apasionante: el soporte para Transacciones. Primero veremos las dos formas de manejar las transas en net 2.0, después las pegas que nos pone Access y por último una propuesta de solución.
En net 1.1 había que crear las transacciones, normalmente a partir de una conexión (cn.BeginTransaction) y la transa era dependiente del acceso a datos (SqlTransaction, OleDbTransaction). Después había que usar esa transa en todos los comandos donde nos interesara, y por último había que llamar a Commit() o a Rollback() sobre esa transa.
try {
transa = cn.BeginTransaction();
OleDbCommand cmd = cn.CreateCommand();
...
transa.Commit();
} catch (Exception) {
transa.Rollback();
}
En net 2.0 han subido el nivel: existe un nuevo TransactionScope, en cuyo ámbito todo lo que hagamos se incluye en esa transa. Además la transa es de alto nivel, por lo que puede incluir operaciones de distintos tipos (accesos a bases de datos mezclados con otros objetos transaccionales). Para terminar, llamamos al método Complete() del scope, y si no lo hacemos y salimos del ámbito (normalmente por culpa de una excepción) se deshace la transa.
using (TransactionScope scope = new TransactionScope()) {
cmd.ExecuteNonQuery();
...
scope.Complete();
}
Bien, pues hay un gran problema: este segundo método, tan elegante, no es admitido por el proveedor Jet OleDB para bases de datos Access. De hecho, no sólo es que no considere la transa, sino que dispara una excepción si intenta lanzarse un comando en el ámbito de esa transa, del tipo InvalidOperationException: "El proveedor 'Microsoft.Jet.OLEDB.4.0' no admite la interfaz ITransactionLocal. Las transacciones locales no están disponibles con el proveedor actual."
Solución que vamos a intentar: no usar directamente TransactionScope, sino unas transacciones de alto nivel propias que tengan un comportamiento similar. En el caso de Sql, usarán internamente TransactionScope, pero en el caso de Access deberán asignarse manualmente a cada comando.
Otro problema secundario es que Access no soporta transacciones anidadas (quizá de ahí venga la incapacidad del proveedor para soportar TransactionScope). En nuestras transacciones tendremos una propiedad que definirá el comportamiento de las transacciones anidadas: soportadas, omitir (incluir en la superior) o no permitir (disparar excepción en ese caso).
Bueno, vamos a implementarlo y a ver cómo queda.

1 Comments:
Respecto a TransactionScope, tiene un poco más de miga de la descrita en esta entrada. Es necesario activar las conexiones de red de MSDTC, tanto en los clientes como en el servidor, tal como se describe en la documentación de Microsoft: ms345266, y en la página www.softwaremix.net/viewtopic-482201.htm
Queda pendiente buscar cómo activar esto dentro del programa de instalación de la aplicación.
Publicar un comentario
<< Home