Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Lanzar excepciones (https://www.clubdelphi.com/foros/showthread.php?t=20360)

cahern4 13-04-2005 18:06:36

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;

Mas en detalle con nombres y todos seria de esta forma, dentro del procedimiento Aumentar_Orden hay una serie de transacciones a la base de datos y puede o no que se llame a otro procedimiento con el nombre Cambiar_Lote, dentro de Cambiar_Lote hay una serie de transacciones a la Base de datos y puede o no que se llame a Cambiar_Grupo, que dentro de Cambiar_Grupo se realizan una serie de transacciones a la base de datos y puede o no que se llame a Cambiar_Caja y en cambiar caja se realizan las ultimas transacciones a la base de datos. Pero cabe resaltar que no siempre se llega al último nivel de los procedimientos, porque eso depende de las condiciones que se den.
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.

Lepe 13-04-2005 19:04:29

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

Código Delphi [-]
procedure aumentar_Orden
begin
try
   transaccion1.StartTransaction...
except 
   mensajepersonalizado al usuario.
    transaccion1.rollback;
end
end;

procedure Cambiar_Lote
begin
try
   transaccion2.StartTransaction...
except 
  mensaje personalizado  
  transaccion2.rollback;
  raise; // con esto re- lanzamos la excepción 
// y hacemos que tambien se produzca una excepción 
// en Aumentar_Caja (el nivel superior)
// por tanto la transacción 1 tambien hace un rollback
end
end;

procedure Cambiar_Grupo
begin
  if valorBooleano then 
    Cambiar_Caja
end;

procedure Cambiar_Caja
begin
try
   transaccion4.StartTransaction...
except 
  mensaje personalizado  
  transaccion4.rollback;
  raise; // con esto re- lanzamos la excepción 
// y hacemos que tambien se produzca una excepción 
// en Cambiar_Grupo, como en ese procedimiento no hay
// ningun try .. except, saltará al nivel superior, o sea a 
// Cambiar_lote, useasé, todo queda controlado.
end
end;

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.

Lepe 13-04-2005 19:25:43

Cita:

Empezado por cahern4
Otro punto importante es que en los demás procedimientos no existe un try y except. Solo está en el procedimeinto principal.

Respondeme a esta pregunta:Suponiendo que se produce una excepción en la transaccion 4 (la más profunda) ¿ estarías haciendo un rollback de las transacciones 2, 3 y 4? ;)

Un saludo

cahern4 13-04-2005 19:39:47

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

Neftali [Germán.Estévez] 14-04-2005 10:33:59

Cita:

Empezado por cahern4
Código Delphi [-]
  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;

Antes de continuar, deberías cambiar el código por éste:

Código Delphi [-]
  datos.celular.StartTransaction;
  try
    Aumentar_Orden(txt_orden.text,form_acceso.usuario.cedula,
                                 form_acceso.usuario.nivel,
                                 Max_Ordenes,Max_Lote,Max_Grupo);
         datos.celular.Commit;
  except
    datos.celular.Rollback;
    messagedlg('Error en la asignación del documento, vuelva a  
      intentarlo',mtinformation,[mbok],0);
   end;

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:

Empezado por cahern4
Otro punto importante es que en los demás procedimientos no existe un try y except. Solo está en el procedimeinto principal.

Si eso es así para cualquier excepción debería llegar al except del procedimiento principal.
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.

Lepe 14-04-2005 11:55:46

Excelente observación Neftali.

Gracias.

cahern4 14-04-2005 22:40:23

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.


La franja horaria es GMT +2. Ahora son las 03:09:17.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi