Transaccion solo se puede deshacer desde un estado pendiente

17/12/2006 - 03:24 por Cristiancito | Informe spam
Estimados:

Intento realizar un rollback al salir de un formulario a una
transaccion de una conexion global de la aplicación. Sin embargo hay
veces en que el sistema me indica el siguiente error:

"La transacción sólo se puede deshacer desde un estado pendiente
(después de haber llamado a BeginTransaction, pero antes de llamar a
Commit)".

La pregunta es ¿Como puedo saber que esto por código antes de
ejecutar el Rollback y no se produzca error?.

Atte.

Cristian.

Preguntas similare

Leer las respuestas

#1 Leonardo Azpurua [mvp vb]
17/12/2006 - 03:43 | Informe spam
"Cristiancito" escribió en el mensaje
news:

Intento realizar un rollback al salir de un formulario a una
transaccion de una conexion global de la aplicación. Sin embargo hay
veces en que el sistema me indica el siguiente error:

"La transacción sólo se puede deshacer desde un estado pendiente
(después de haber llamado a BeginTransaction, pero antes de llamar a
Commit)".

La pregunta es ¿Como puedo saber que esto por código antes de
ejecutar el Rollback y no se produzca error?.


Hola Christiancito,


Rollback es exactamente lo contrario de Commit. Exactamente lo contrario
significa que si ejecutas el Rollback es porque no puedes ejecutar el
Commit, y si ejecutas el Commit no necesitas ejecutar el Rollback.

Normalmente vas a hacer algo del tipo de:

Try
BeginTransaction

If HayUnErrorAqui Then
Throw New Excepction("Hubo un error")
End If
CommitTransaction
Catch ex As Exception
RollbackTransaction
NotificarErrorAlUsuario(ex.Message)
End Try

si te fijas, la unica manera de llamar a Rollback es que no hayas llamado a
Commit, y si efectivamente llamas a Commit, nunca llamarás a Rollback.

Rollback y Commit deben estar en dos ramas de ejecución totalmente
diferentes y mutuamente excluyentes: tu problema no es de detectar si debes
o no hacer el Rollback en función de si se hizo o no el Commit (eso lo
resolverias colocando un flag booleano). La solución, sea cual fuere tu
código, es estructurarlo correctamente.


Salud!
Respuesta Responder a este mensaje
#2 Cristián Patricio Muñoz Tello
17/12/2006 - 12:07 | Informe spam
Leonardo:

Lo comprendo, pero quizás si te explico mas en detalle me puedas
entender o corregir.

Todo viene a colación porque tengo dos objetos datawindow (un producto
de sybase) cada uno de los cuales esta enlazado a una tabla. Uno de ellos
esta enlazado a una tabla maestra y el otro a una tabla detalle. Las tablas
maestro y detalle estan relacionadas mediante una clave foranea, esto
implica que para agregar una fila a detalle debo tener agregada la clave
foranea correspondiente en la tabla maestra. Es por ello que necesito
iniciar una transaccion para agregar la fila en la tabla cabecera antes de
comenzar a agregar detalles, para luego realizar el Commit a la transaccion
solo una vez que el usuario haya presionado el boton grabar. Sin embargo es
probable que el usuario salga de la ventana sin grabar pero con la
transaccion pendiente producto de que haya agregado ya algunos datos sin
presionar grabar. El problema es que el usuario puede salir tambien de la
ventana sin haber realizado nada por lo tanto sin que se haya iniciado
transaccion alguna o cuando esta ya se haya completado. Esto hace que el
código de rollback que yo ponga al salir de la ventana solo me funcione
cuando hayan transacciones pendientes y me arroje el error mencionado cuando
no hayan transacciones pendientes.

Alguna sugerencia?

Atte.

Cristian Muñoz Tello.


"Leonardo Azpurua [mvp vb]" <l e o n a r d o (arroba) m v p s (punto) o r g>
escribió en el mensaje news:

"Cristiancito" escribió en el mensaje
news:

Intento realizar un rollback al salir de un formulario a una
transaccion de una conexion global de la aplicación. Sin embargo hay
veces en que el sistema me indica el siguiente error:

"La transacción sólo se puede deshacer desde un estado pendiente
(después de haber llamado a BeginTransaction, pero antes de llamar a
Commit)".

La pregunta es ¿Como puedo saber que esto por código antes de
ejecutar el Rollback y no se produzca error?.


Hola Christiancito,


Rollback es exactamente lo contrario de Commit. Exactamente lo contrario
significa que si ejecutas el Rollback es porque no puedes ejecutar el
Commit, y si ejecutas el Commit no necesitas ejecutar el Rollback.

Normalmente vas a hacer algo del tipo de:

Try
BeginTransaction

If HayUnErrorAqui Then
Throw New Excepction("Hubo un error")
End If
CommitTransaction
Catch ex As Exception
RollbackTransaction
NotificarErrorAlUsuario(ex.Message)
End Try

si te fijas, la unica manera de llamar a Rollback es que no hayas llamado
a Commit, y si efectivamente llamas a Commit, nunca llamarás a Rollback.

Rollback y Commit deben estar en dos ramas de ejecución totalmente
diferentes y mutuamente excluyentes: tu problema no es de detectar si
debes o no hacer el Rollback en función de si se hizo o no el Commit (eso
lo resolverias colocando un flag booleano). La solución, sea cual fuere tu
código, es estructurarlo correctamente.


Salud!


Respuesta Responder a este mensaje
#3 Leonardo Azpurua [mvp vb]
17/12/2006 - 14:09 | Informe spam
"Cristián Patricio Muñoz Tello" escribió en el mensaje
news:%23%
Leonardo:

Lo comprendo, pero quizás si te explico mas en detalle me puedas
entender o corregir.

Todo viene a colación porque tengo dos objetos datawindow (un producto
de sybase) cada uno de los cuales esta enlazado a una tabla. Uno de ellos
esta enlazado a una tabla maestra y el otro a una tabla detalle. Las
tablas maestro y detalle estan relacionadas mediante una clave foranea,
esto implica que para agregar una fila a detalle debo tener agregada la
clave foranea correspondiente en la tabla maestra. Es por ello que
necesito iniciar una transaccion para agregar la fila en la tabla cabecera
antes de comenzar a agregar detalles, para luego realizar el Commit a la
transaccion solo una vez que el usuario haya presionado el boton grabar.
Sin embargo es probable que el usuario salga de la ventana sin grabar pero
con la transaccion pendiente producto de que haya agregado ya algunos
datos sin presionar grabar. El problema es que el usuario puede salir
tambien de la ventana sin haber realizado nada por lo tanto sin que se
haya iniciado transaccion alguna o cuando esta ya se haya completado. Esto
hace que el código de rollback que yo ponga al salir de la ventana solo me
funcione cuando hayan transacciones pendientes y me arroje el error
mencionado cuando no hayan transacciones pendientes.

Alguna sugerencia?



Hola.

Ya decia yo que debia de haber algo malo en tu código :-)

Todo ese asunto de los controles enlazados, DataWindows, DataControls,
DataSets etcetera, normalmente no sirve más que para producir
"contracepciones", un poco al estilo de Rube Goldberg. Sus inventores y
promotores van a pasar toda la eternidad en un infierno donde todo será
bonito y familiar, pero donde nada funcionará de la manera esperada. Por
ejemplo, para encender la luz de la cocina será necesario colocar el equipo
de audio debajo de la estufa, abrir el chorro del fregadero, subir y bajar
la escalera y por ultimo jalar la cadena del inodoro del baño principal. Y
se lo tendrán bien merecido: cuantos buenos programadores y buenos proyectos
no han naufragado en el mar de extremas dificultades inducidas por los
DataControl, afines y derivados!

De todas maneras, puedes utilizar un indicador lógico en la forma maestra
para indicar si tienes o no una transaccion pendiente. Es decir, al momento
en que se modifica algo en la forma de cabecera, inicias la transacción y
levantas el indicador: enTransaccion = True. Cuando el usuario decide que
quiere registrar los cambios, confirmas la transaccion y bajas el indicador:
enTransaccion = False. Si el usuario cierra la forma sin guardar los datos,
simplemente verificas el estado de enTransaccion. Si es True haces el
Rollback.

Debes estar consciente de que los registros modificados en el contexto de
una transaccion no son accesibles a otros usuarios para su modificacion.
Mantener transacciones activas en un equipo mientras el usuario tiene el
control es la mejor manera de limitar la escalabilidad de una aplicacion.


Salud!
Respuesta Responder a este mensaje
#4 Alberto Poblacion
17/12/2006 - 15:30 | Informe spam
"Cristián Patricio Muñoz Tello" wrote in message
news:%23%
El problema es que el usuario puede salir tambien de la ventana sin haber
realizado nada por lo tanto sin que se haya iniciado transaccion alguna o
cuando esta ya se haya completado. Esto hace que el código de rollback que
yo ponga al salir de la ventana solo me funcione cuando hayan
transacciones pendientes y me arroje el error mencionado cuando no hayan
transacciones pendientes.

Alguna sugerencia?



Sugerencia: Rediseñar por completo todo el funcionamiento de la
aplicación. A no ser que se trate de una aplicación monousuario, y que
ningún otro proceso acceda a la base de datos mientras este programa la está
utilizando, el funcionamiento que has descrito es una receta para el
desastre. Cuando inicias la transacción y te pones a operar con la base de
datos, se van poniendo bloqueos sobre todos los recursos que toque el
programa. Si otro programa intenta acceder a esos datos (por ejemplo,
alguien trata de sacar un listado desde otro puesto de trabajo), el otro
programa se queda bloqueado, esperando que termine la transacción para que
se quiten los bloqueos. Si en medio de la transacción se espera una
intervención del usuario, como en el caso que has descrito, todos los demás
puestos de trabajo se van a quedar bloqueados hasta que el usuario termine
de realizar el proceso (incluido el irse a tomar un café mientras deja la
ventana abierta en pantalla con los datos a medio introducir). Por ese
motivo, todos los manuales de programación indican que las transacciones
deben ser breves, y desde luego nunca debe esperarse una intervención del
usuario en medio de una transacción. Hay que pedir al usuario todos los
datos necesarios, y una vez que se tienen esos datos en memoria, iniciar la
transacción, realizar las operaciones, y cerrar la transacción. Y una vez
cerrada, si hubo algún error, se informa al usuario.
Respuesta Responder a este mensaje
#5 Cristián Patricio Muñoz Tello
17/12/2006 - 15:42 | Informe spam
Muchas Gracias Alberto.

A partir de tu respuesta y la de leonardo que quedado mas claro acerca
de como llevar este asuntito, y he realizado algunas modificaciones al
código para hacer esto mas fluido.

Muchas gracias.

Cristian Muñoz Tello.


"Alberto Poblacion"
escribió en el mensaje news:
"Cristián Patricio Muñoz Tello" wrote in message
news:%23%
El problema es que el usuario puede salir tambien de la ventana sin haber
realizado nada por lo tanto sin que se haya iniciado transaccion alguna o
cuando esta ya se haya completado. Esto hace que el código de rollback
que yo ponga al salir de la ventana solo me funcione cuando hayan
transacciones pendientes y me arroje el error mencionado cuando no hayan
transacciones pendientes.

Alguna sugerencia?



Sugerencia: Rediseñar por completo todo el funcionamiento de la
aplicación. A no ser que se trate de una aplicación monousuario, y que
ningún otro proceso acceda a la base de datos mientras este programa la
está utilizando, el funcionamiento que has descrito es una receta para el
desastre. Cuando inicias la transacción y te pones a operar con la base de
datos, se van poniendo bloqueos sobre todos los recursos que toque el
programa. Si otro programa intenta acceder a esos datos (por ejemplo,
alguien trata de sacar un listado desde otro puesto de trabajo), el otro
programa se queda bloqueado, esperando que termine la transacción para que
se quiten los bloqueos. Si en medio de la transacción se espera una
intervención del usuario, como en el caso que has descrito, todos los
demás puestos de trabajo se van a quedar bloqueados hasta que el usuario
termine de realizar el proceso (incluido el irse a tomar un café mientras
deja la ventana abierta en pantalla con los datos a medio introducir). Por
ese motivo, todos los manuales de programación indican que las
transacciones deben ser breves, y desde luego nunca debe esperarse una
intervención del usuario en medio de una transacción. Hay que pedir al
usuario todos los datos necesarios, y una vez que se tienen esos datos en
memoria, iniciar la transacción, realizar las operaciones, y cerrar la
transacción. Y una vez cerrada, si hubo algún error, se informa al
usuario.


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida