FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
Lanzar excepciones
Un saludo a todos en el foro. Y desde ya, gracias por la ayuda.
Tengo un problema y escribo para ver si me pueden ayudar, quizá sea algo muy simple pero la verdad no le puedo llegar. El caso es el siguiente: tengo un procedimiento principal, el cual comienza con un try y finaliza con un except, en medio del try se hace llamado a otro procedimiento que lo que hace son algunas transacciones en la base de datos, y dentro de ese segundo procedimiento puede que se llame o no a otro procedimiento que también lo que hace son transacciones a la base de datos, y así sucesivamente hasta llegar a 5 niveles de procedimientos. El problema que tengo es que si en alguno de esos procedimientos se da un error de acceso a la base de datos o se presenta alguna inconsistencia debo de hacer Rollback a las demás transacciones que se realizaron en los procedimientos anteriores. No se si yo puedo lanzar una excepción de un procedimiento a otro hasta llegar al except principal donde se hace el rollback de todas las transacciones, por eso les escribo para que me orienten o me den un luz. Ya que a como está el código en este momento no me cae al except principal, nada mas me da un error de base de datos y el programa se me cuelga. A continuación adjunto el código para que se den una idea de que es lo que necesito hacer. Código:
try begin datos.celular.StartTransaction; Aumentar_Orden(txt_orden.text,form_acceso.usuario.cedula, form_acceso.usuario.nivel, Max_Ordenes,Max_Lote,Max_Grupo); datos.celular.Commit; end; except datos.celular.Rollback; messagedlg('Error en la asignación del documento, vuelva a intentarlo',mtinformation,[mbok],0); end; Otro punto importante es que en los demás procedimientos no existe un try y except. Solo está en el procedimeinto principal. Un saludo a todos y muchísimas gracias por leer mi mensaje, espero haberme explicado bien. |
#2
|
||||
|
||||
Una excepción busca el del try except más cercano, si no tienes ninguno en
tu aplicación, se genera el evento Application.OnException (delphi 6 o superior, componente TapplicationEvents, si mal no recuerdo), Si tampoco tienes código en ese evento, o no la cancelas la excepción, entonces aparece el mensaje en pantalla, y casi siempre en inglés. Tu caso particular es complejo, pero es simple la solución: Tal como lo comentas, las llamadas en cascada se pueden producir así: Aumentar_Orden Cambiar_Lote, Cambiar_Grupo, Cambiar_Caja
Es decir, el programa iría de arriba de este código, hacia abajo, pero cuando se produce la excepción, hace lo que hay en el try except, y al estar la palabra reservada raise;, el código se empieza a ejecutar hacia arriba, entrando en todas las cláusulas except y deshaciendo todos los cambios hechos en la base de datos. Un saludo, y espero se entienda.
__________________
Si usted entendió mi comentario, contácteme y gustosamente, se lo volveré a explicar hasta que no lo entienda, Gracias. Última edición por Lepe fecha: 13-04-2005 a las 19:18:14. |
#3
|
||||
|
||||
Cita:
Un saludo
__________________
Si usted entendió mi comentario, contácteme y gustosamente, se lo volveré a explicar hasta que no lo entienda, Gracias. Última edición por Lepe fecha: 13-04-2005 a las 19:28:23. |
#4
|
|||
|
|||
Por si solas las transacciones 2, 3 y 4 no se pueden cancelar, porque además de eso se debería de cancelar la 1. O sea se cancelaría toda la transacción, 1, 2, 3, 4. Esto porque si se presenta un error (en este caso se tomaría como una excepción) en la información, por ejemplo un insert de algo que ya existe, en el momento en que la aplicación está ejecutando la transacción 4 se debe cancelar la 4 y todas las demás que se ejecutaron antes, es decir 3, 2 y 1.
Pero si el error (excepción en este caso) se da al momento en que la aplicación va por la transacción 2, se cancela la 2 y la 1 nada más. Pero para poder cancelar 2, 3 y 4 solamente no se puede, ya que faltaría cancelar la 1. Espero haberte entendido la pregunta y espero haberte contestado lo que deseas. Gracias por tu ayuda, y si entendí tu mensaje anterior, estoy implementando la solución y tan pronto le haga las pruebas del caso te aviso. Tu ayuda es de suma importancia para mí, de verdad gracias por brindar este tipo de ayuda. Saludos |
#5
|
||||
|
||||
Cita:
No puedes poner el StartTransaction dentro del Try, porque si falla el StartTransaction intentarás hacer el RollBack de algo que ha fallado y que no has hecho. Cita:
De todas formas yo revisaría las soluciones que te han propuesto más arriba, donde cada procedimiento capture sus excepciones (para hacer su rollback) y luego propague la excepción hacia arriba con un raise.
__________________
Germán Estévez => Web/Blog Guía de estilo, Guía alternativa Utiliza TAG's en tus mensajes. Contactar con el Clubdelphi P.D: Más tiempo dedicado a la pregunta=Mejores respuestas. |
#6
|
||||
|
||||
Excelente observación Neftali.
Gracias.
__________________
Si usted entendió mi comentario, contácteme y gustosamente, se lo volveré a explicar hasta que no lo entienda, Gracias. |
#7
|
|||
|
|||
Gracias a los 2 por las respuestas y soluciones que me han dado.
Sobre lo que plantea Neftali ya lo modifique en mi código. El StartTransaction lo saque del try. Ahora me surge una duda con lo que plantea Lepe, y es la siguiente: Yo puedo en el procedimiento Aumentar_Orden hacer el llamado al StartTransaction y luego hacer otro StartTransaction en el procedimiento Cambiar_Lote, aun sin haber hecho el commit del StartTransaction que llame en el procedimiento Aumentar_Orden. Esto lo pregunto porque tengo 5 procedimientos o sea serian 5 StartTransaction que se pueden dar sin haber hecho un commit, porque si esto se puede hacer así como lo planteo supongo que entonces si estoy llamando el rollback desde el procedimiento 3 solo se cancelaran las transacciones del procedimiento 3, y luego como subo la excepción cae al except del procedimiento 2 que como también tiene un rollback debería de cancelar solo las transacciones del procedimiento 2, y así para atrás hasta llegar al primer procedimiento, y luego bastaría con hacer un solo commit. ¿Esto es correcto como lo planteo o estoy totalmente equivocado? Y nuevamente gracias. |
|
|
|