Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Manejo de errores en Master Detail (https://www.clubdelphi.com/foros/showthread.php?t=26748)

Carlos Hurtado 02-11-2005 15:38:54

Manejo de errores en Master Detail
 
Hola Amigos nuevemente estoy recurriendo a ustedes para que me ayuden a solucionar este problema:
Tengo Firebird 1.5 con Delphi 7
IbTransaction1. Params
read_commited
rec_version
nowait

La Tabla Detalle (ValesDetalle) proviene de un stringgrid y la Tabla Maestro(ValesMaestro) proviene de datos de cliente mas la suma del campo Total de ValesDetalle.

En las inserciones de la Tabla Maestro y la Tabla Detalle no tengo problemas, ellos estan cuando tengo que actualizar la Tabla StockMaestro del campo Cantidad de la Tabla Detalle.
Para esto lo hago con una Stored Procedure que debe manejar las stes. situaciones:
Si no hay stock debe hacer un rollback
Si hay un lock_conflict deberia repetir la procedure hasta hacer el update
Si hay cualquier otro error debe hacer un rollback.

La Procedure


CREATE PROCEDURE ACTUALIZA_VALESDETALLE(
VID_VALE VARCHAR(12),
VID_PRODUCTO VARCHAR(12),
VCANTIDAD DECIMAL(7,2),
VDESCRIPCION VARCHAR(40),
VVALORUNITARIO NUMERIC,
VTOTAL NUMERIC)
RETURNS (
FLAG SMALLINT)
AS
DECLARE VARIABLE V_STOCK DECIMAL(7,2);
BEGIN
INSERT INTO VALESDETALLE
(
ID_VALE,
ID_PRODUCTO,
CANTIDAD,
DESCRIPCION,
VALORUNITARIO,
TOTAL
)
VALUES
(
:VID_VALE,
:VID_PRODUCTO,
:VCANTIDAD,
:VDESCRIPCION,
:VVALORUNITARIO,
:VTOTAL
);
SELECT EXISTENCIA FROM STOCKMAESTRO WHERE ID_PRODUCTO = :VID_PRODUCTO
INTO :V_STOCK;
IF (:V_STOCK >= :VCANTIDAD) THEN
BEGIN
UPDATE STOCKMAESTRO
SET EXISTENCIA = :V_STOCK - :VCANTIDAD
WHERE ID_PRODUCTO = :VID_PRODUCTO;
FLAG = 0;
END
ELSE
EXCEPTION NO_STOCKDETALLE;
WHEN EXCEPTION NO_STOCKDETALLE DO
BEGIN
FLAG = 1;
END
WHEN GDSCODE lock_conflict DO
BEGIN
¡¡¡¡NO SE QUE HACER!!!
END
WHEN ANY DO
BEGIN
FLAG = 1;
END
END ^



Y el procedimiento en Delphi
///////
For a := 1 to stringGrid1.RowCount - 1 do
begin
with IbStoredProc1 do
begin
Close;
IbStoredProc1.StoredProcName := 'ACTUALIZA_VALESDETALLE';
ParamByName('VID_VALE').AsString := VCodigo;
ParamByName('VID_PRODUCTO').AsString := StringGrid1.Cells[4,a];
ParamByName('VCANTIDAD').AsFloat := StrToFloat(StringGrid1.Cells[0,a]);
ParamByName('VDESCRIPCION').AsString := StringGrid1.Cells[1,a];
ParamByName('VVALORUNITARIO').AsInteger := StrToInt(StringGrid1.Cells[2,a]);
ParamByName('VTOTAL').AsInteger := Total;
Prepare;
ExecProc;
VFlag := ParamByName('FLAG').AsInteger;
end;
if VFlag = 1 then
Break;
end;
Label6.Caption := IntToStr(VFlag);
if VFlag = 1 then
begin
IbTransaction1.RollBack;
s := StringGrid1.Cells[0,a] + ' ' + StringGrid1.Cells[1,a];
MessageDlg('Registro ' + s + ' no tiene stock suficiente',mtError,[mbOk], 0);
end
else
IbTransaction1.Commit;
end;
end;

En base a lo planteado, que debo hacer para manejar el lock_conflict


Muchas gracias.

Lepe 03-11-2005 10:01:51

Exception conflicto

Es decir, te creas una excepción y desde ahí la lanzas, Firebird deshace los cambios de forma automática según el caso:

- Si es un SP de SELECT, puede haber varios SUSPEND, solo se deshace los cambios desde el último SUSPEND;
- Si es un SP ejecutable, no debe haber SUSPEND, por tanto se deshace el SP al completo.

Deberias olvidarte del Flag, y especificar el mensaje directamente en la excepción creada.

Carlos Hurtado 03-11-2005 13:23:41

Hola Amigos, un saludo Lepe. Muy agradecido de tu sugerencia.
pero me gustaria profundizar mas sobre el tema.

Como se desprende del codigo Delphi la procedure Actualiza_ValesDetalle se repite tantas veces como lineas tenga el stringgrid que alimenta la tabla Detalle (ValesDetalle). Por lo tanto si ocurre un error del tipo lock_conflict es porque el Parametro nowait no permitio actualizar la transaccion ya que habia que esperar que terminara otra en proceso.
Pues bien, lo que yo pienso es que si sucede un lock_conflict lo logico seria poder repetir la procedure ya que al hacerlo no existiria la condicion de lock_conflict y me permitiria hacer el commit de toda la transaccion.
Por eso insisto como puedo hacer que este codigo me haga repetir la instruccion de update:

WHEN GDSCODE lock_conflict DO
BEGIN
¡¡¡¡NO SE QUE HACER!!!
END

Ojala haya alguna sugerencia.
Muchas gracias.


La franja horaria es GMT +2. Ahora son las 16:11:30.

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