Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Controlar Commit y Rollback (https://www.clubdelphi.com/foros/showthread.php?t=35276)

lucasarts_18 06-09-2006 04:33:35

Controlar Commit y Rollback
 
Hola compañeros del club:

Estoy realizando mantenciones a un sistema hecho en Delphi 4 y SQL Server 2000, y necesito cambiar algo de caracter importantísimo.

En primer lugar las transacciones están aisladas, ¿que quiero decir con esto?, pues que cada procedimiento almacenado de la base de datos contiene commit y rollback, siendo esto último no un problema para los mantenedores simples, por ejemplos productos, clientes, bodegas, etc...
Mi problema radica es que los modulos de ventas por ejemplo el de factura, al momento de grabar llama a varios SP (Ingresa Factura, Detalle Factura, Cta Corriente del cliente, Actualiza Stock, Etc....) lo cual al momento de producirse un fallo en el segundo u tercero.... SP me deja incosistencias en la BD ya que se produce un commit en cada procedimiento.
Sin lugar a dudas en estos casos lo mejor es controlarlo desde el programa todo lo referente a los commit y rollback, pero aquí yace mi gran duda...
Creo que con el código se entenderá un poco mejor:

Código Delphi [-]
     if combo_vendedor.text ='' then
     begin
        MessageDlg('Ingrese el Código Vendedor', mtWarning, [mbOk],0);
        combo_vendedor.Setfocus;
        exit;
     end;

     if (edt_totalguia.Text ='') then
     begin
        MessageDlg('Debe Calcular el Valor Total de la Factura',mtWarning,[mbOk],0);
        btn_Calculo.SetFocus;
        exit;
     end;

     if Ingresar then
     begin
        Msg :='¿Desea Grabar el Ingreso de la Guía?';
        if MessageDlg(Msg, mtConfirmation,[mbyes, mbNo],0) = mrYes then
        begin
           if (opcion_pago.ItemIndex in [0]) then
           begin
              Msg :='Favor, confirmar la opción de Pago con el CLIENTE'+ #13 + '< CONTADO >'+ #13 +'Si está correcto oprima [Ok], de lo contrario presione [Cancel]';
              if MessageDlg(Msg, mtConfirmation,[mbOK, mbCancel],0) = mrCancel then
              Exit;
           end
           else
           begin
              Msg :='Favor, confirmar la opción de Pago con el CLIENTE '+ #13 + '< CRÉDITO >'+ #13 +'Si está correcto oprima [Ok], de lo contrario presione [Cancel]';
              if MessageDlg(Msg, mtConfirmation,[mbOK, mbCancel],0) = mrCancel then
              Exit;
           end;
           IngresarGuia;
           IngresarCorrelativo;
           lv_i := 1;
           while (lv_i <= grd_Detalle.RowCount -1) do
           begin
              IngresarDetalleGuia;
              ActualizarStockProducto;
              lv_i :=lv_i+1;
           end;
           MessageDlg('Guía de Despacho Ingresada Exitosamente.'+#13+'Ahora Deberá Imprimir.',mtInformation,[mbOk],0);
           btn_buscarguia.Enabled := False;
           btn_Nuevo.Enabled := False;
           btn_Imprimir.Enabled := True;
           btn_Grabar.Enabled := False;
           btn_calculo.Enabled := False;
           btn_Salir.Enabled := False;
           PrecioNormal := 0;
           PrecioOferta := 0;

        end;
     end;
end;

Supongamos IngresarGuia, IngresarCorrelativo son procedimientos delphi que a la vez llaman a procedimientos de SQL Server que contiene commit, mi idea es quitar los commit y en caso de error capturar el código error devuelto por la BD y este asignarlo a una variable pública del formulario para controlar el error, pero no se me ocurre muy bien como implementarlo, según ustedes ¿qué opción me recomendarían ?

Esperando que toda esta parafernalía se entienda :p

Hasta Luego -

kalimero 06-09-2006 09:59:24

Código Delphi [-]
try
    if not(conexion.InTransaction) then conexion.BeginTrans;
    ingresarguia;
    ingresarcorrelativo;
    conexion.commit; //todo ha ido bien y confirmamos
except
    //Capturamos la excepcion y hacemos lo que queramos
    //Deshacemos la transaccion
    conexion.Rollback;
end;

jachguate 06-09-2006 15:54:30

Veo un defecto en el código de kalimero y es que se "traga" la excepción, por lo que aún cuando se ha realizado correctamente el rollback, pueden haber fallos posteriores debido a esto:

yo lo dejaría como:

Código Delphi [-]
Conexion.StartTransaction;
try
  HacerTodoLoQueSeQuiera;
  Conexion.Commit;
except
  Conexion.Rollback;
  raise; //esta línea eleva nuevamente la excepción original después del rollback
end;
Hasta luego.

;)

kalimero 06-09-2006 17:27:46

Efectivamente Jachguate. No lo he dicho porque doy por supuesto que el interesado ya tenia claro este tema. Me he centrado en el objetivo de la pregunta era saber donde se ponen la llamadas a "begintrans" y "commit".
De todas formas el codigo correcto es el que tu has apuntado.

Saludos

jachguate 06-09-2006 18:13:21

Cita:

Empezado por kalimero
No lo he dicho porque doy por supuesto que el interesado ya tenia claro este tema.

Pero luego hay cada pelao que solo copia y pega... :cool:

lucasarts_18 07-09-2006 05:47:32

Cita:

Empezado por jachguate

yo lo dejaría como:


Código Delphi [-]
Conexion.StartTransaction;
try
HacerTodoLoQueSeQuiera;
Conexion.Commit;
except
Conexion.Rollback;
raise; //esta línea eleva nuevamente la excepción original después del rollback
end;




Hasta luego.

;)

No entiendo del todo lo que te refieres con HacerTodoLoQueSeQuiera;
¿Realmente es poner todos los procedimientos delphi que tengo mas arriba en uno solo?

Con referente a tu último comentario, creo que no esta acorde a un forista que tiene más de 600 mensajes y que es motivo claro de un hecho de aprender y no salir del apuro...:mad:

Hasta Luego y gracias...:cool:

jachguate 07-09-2006 16:53:40

Cita:

Empezado por lucasarts_18
No entiendo del todo lo que te refieres con HacerTodoLoQueSeQuiera;
¿Realmente es poner todos los procedimientos delphi que tengo mas arriba en uno solo?

No me refería a poner todo en uno solo, en realidad HacerTodoLoQueSeQuiera es eso... podes llamar a procedimientos, funciones, etc. Tantos como querras. ;)

Cita:

Empezado por lucasarts_18
Con referente a tu último comentario, creo que no esta acorde a un forista que tiene más de 600 mensajes y que es motivo claro de un hecho de aprender y no salir del apuro...:mad:

Hasta Luego y gracias...:cool:

Lamento no haber sido explicito y dar pie al malentendido, pero en realidad no me refería a vos. Te explico: Yo soy de los que creen que toda respuesta dada en estos foros se está dando en realidad a la comunidad, pues hay y habrán otros que un día se toparán con este tema dentro de una búsqueda... y dentro de esos, seguramente habrá algun pelao de esos que solo copian y pegan. Creeme que después de reponder, me quedé pensando también que esos pelaos, seguramente no llegarán a leer mi mensaje.. :D

Saludos.

;)

lucasarts_18 08-09-2006 02:28:41

Cita:

Empezado por jachguate
Lamento no haber sido explicito y dar pie al malentendido, pero en realidad no me refería a vos. Te explico: Yo soy de los que creen que toda respuesta dada en estos foros se está dando en realidad a la comunidad, pues hay y habrán otros que un día se toparán con este tema dentro de una búsqueda... y dentro de esos, seguramente habrá algun pelao de esos que solo copian y pegan. Creeme que después de reponder, me quedé pensando también que esos pelaos, seguramente no llegarán a leer mi mensaje.. :D

;)

Gracias por la aclaración, y gracias a ambos por resolver mi duda...

Hasta Luego - :)

cacu 08-11-2010 00:12:41

tarde
 
Este problema podria tratarse con procedimientos anidados.
por otro lado puedes captutar el error en el mismo procedimiento
if @@erro<> o goto un_error:

un_error:
rolback
return(1);

aqui ya con la devolucion 1 puedes gestionar este erro

tarde la respuesta. jajaj y ademas no se si hubiese servido en el contextp de esta necesidad

jachguate 08-11-2010 22:57:41

Cita:

Empezado por cacu (Mensaje 381627)
por otro lado puedes captutar el error en el mismo procedimiento
if @@erro<> o goto un_error:

un_error:
rolback
return(1);

aqui ya con la devolucion 1 puedes gestionar este erro


Francamente nunca he sido de la idea de hacer un rollback dentro de un procedimiento dentro de la propia base de datos.. no solo no es soportado por todos los motores, sino deja poca oportunidad para la re-utilización de código, ya que es indefinido (o al menos varía de motor a motor) cuál será el comportamiento con posibles próximas operaciones que uno podría suponer deben ir en el contexto de la misma transacción. En mi opinión, el control de las transacciones debe ser siempre explícito y desde fuera de los procedimientos y funciones almacenados.

Mis 2 centavos.


La franja horaria es GMT +2. Ahora son las 04:51:27.

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