Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 13-04-2005
cahern4 cahern4 is offline
Registrado
 
Registrado: may 2003
Posts: 8
Poder: 0
cahern4 Va por buen camino
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.
Responder Con Cita
  #2  
Antiguo 13-04-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
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.
__________________
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.
Responder Con Cita
  #3  
Antiguo 13-04-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
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
__________________
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.
Responder Con Cita
  #4  
Antiguo 13-04-2005
cahern4 cahern4 is offline
Registrado
 
Registrado: may 2003
Posts: 8
Poder: 0
cahern4 Va por buen camino
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
Responder Con Cita
  #5  
Antiguo 14-04-2005
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
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.
__________________
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.
Responder Con Cita
  #6  
Antiguo 14-04-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
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.
Responder Con Cita
  #7  
Antiguo 14-04-2005
cahern4 cahern4 is offline
Registrado
 
Registrado: may 2003
Posts: 8
Poder: 0
cahern4 Va por buen camino
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.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 12:25:13.


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