PDA

Ver la Versión Completa : Transaccion, captura de error


vmorillos
20-01-2011, 15:22:12
Hola a todos, aqui pidiendo su consejo nuevamente. Debo mencionar primero que uso Zeos 6.6.6, mysql 5 y delphi 7.
Tengo tres tablas: una factura, el detalle de la factura (zDetalle) y una tabla producto. La tabla detalle como es logico tiene una llave compuesta por el codigo de la factura y el codigo de los productos.
Lo que quiero es capturar el error al momento de insertar una llave duplicada en la tabla detalle, para lo cual uso el siguiente codigo:

Código Delphi [-] (http://www.clubdelphi.com/foros/#)procedure TForm1.Button1Click(Sender: TObject); var iCodigoProducto,iCodigoFactura,iCantidad : integer; fPrecio : Double; begin iCodigoProducto:=StrToInt(edProducto.Text); iCodigoFactura:=StrToInt(edFactura.Text); iCantidad:=StrToInt(edCantidad.Text); fPrecio:=StrToFloat(edPrecio.Text); ZConnection1.StartTransaction; try zDetalle.Insert; zDetalleProdCodigo.Value:=iCodigoProducto; zDetalleFactCodigo.Value:=iCodigoFactura; zDetalleCantidad.Value:=iCantidad; zDetallePrecio.Value:=fPrecio; zDetalle.Post; // <--- El error es lanzado aqui y no en el EXCEPT ZConnection1.Commit; except on E:EZSQLException do begin ShowMessage('Error codigo: '+IntToStr(E.ErrorCode)+' - '+E.Message); ZConnection1.Rollback; end; end; end;


Pero el error es lanzado justo después de intentar el post y nunca entra al except y muestra el showmessage. Es extraño porque he puesto este otro codigo en otro botón y si entra al except:


procedure TForm1.Button2Click(Sender: TObject);
begin
ZQuery1.SQL.Clear;
ZQuery1.SQL.Add('SELECT FROM');
ZQuery1.Active:=false;

ZConnection1.StartTransaction;

try
ZQuery1.active:=true;

ZConnection1.Commit;
except
on E:EZSQLException do
begin
ShowMessage('Error codigo: '+IntToStr(E.ErrorCode)+' - '+E.Message);
ZConnection1.Rollback;
end;

end;
end;


Espero su ayuda y muchas gracias de antemano a todos.

PD: En el uses he agregado "ZDbcIntfs"

vmorillos
20-01-2011, 15:34:04
Hola a todos, aqui pidiendo su consejo nuevamente. Debo mencionar primero que uso Zeos 6.6.6, mysql 5 y delphi 7.
Tengo tres tablas: una factura, el detalle de la factura (zDetalle) y una tabla producto. La tabla detalle como es logico tiene una llave compuesta por el codigo de la factura y el codigo de los productos.
Lo que quiero es capturar el error al momento de insertar una llave duplicada en la tabla detalle, para lo cual uso el siguiente codigo:


procedure TForm1.Button1Click(Sender: TObject);
var
iCodigoProducto,iCodigoFactura,iCantidad : integer;
fPrecio : Double;
begin
iCodigoProducto:=StrToInt(edProducto.Text);
iCodigoFactura:=StrToInt(edFactura.Text);
iCantidad:=StrToInt(edCantidad.Text);
fPrecio:=StrToFloat(edPrecio.Text);


ZConnection1.StartTransaction;
try
zDetalle.Insert;

zDetalleProdCodigo.Value:=iCodigoProducto;
zDetalleFactCodigo.Value:=iCodigoFactura;
zDetalleCantidad.Value:=iCantidad;
zDetallePrecio.Value:=fPrecio;

zDetalle.Post; // <--- El error es lanzado aqui y no en el EXCEPT
ZConnection1.Commit;
except
on E:EZSQLException do
begin
ShowMessage('Error codigo: '+IntToStr(E.ErrorCode)+' - '+E.Message);
ZConnection1.Rollback;
end;

end;
end;



Pero el error es lanzado justo después de intentar el post y nunca entra al except y muestra el showmessage. Es extraño porque he puesto este otro codigo en otro botón y si entra al except:


procedure TForm1.Button2Click(Sender: TObject);
begin
ZQuery1.SQL.Clear;
ZQuery1.SQL.Add('SELECT FROM');
ZQuery1.Active:=false;

ZConnection1.StartTransaction;

try
ZQuery1.active:=true;

ZConnection1.Commit;
except
on E:EZSQLException do
begin
ShowMessage('Error codigo: '+IntToStr(E.ErrorCode)+' - '+E.Message);
ZConnection1.Rollback;
end;

end;
end;


Espero su ayuda y muchas gracias de antemano a todos.

PD: En el uses he agregado "ZDbcIntfs"

BlueSteel
20-01-2011, 15:41:12
Hola vmorillos

No es por querer modificar tu forma de trabajar, pero veo que estas insertando los datos directamente a la tabla.. que pasa si una vez que ingresa todo la persona se arrepiente de crear la Factura.... :confused:

Bueno, tampoco quiero imponerte mi forma de trabajar (en realidad si...eso quiero :D:D:D)

Yo para estos casos utilizo una Tabla de Memoria, en donde inserto todos los datos de los productos (para el caso, Detalle Factura)...

En el caso de insertar un codigo de producto que ya esta insertado, primero pregunto si dicho articulo existe.... si existe, despues pregunto si ya ha sido ingresado en el Detalle Factura... si ya fue ingresado lanzo mensaje de que el articulo ya existe, desea modificar o ingresar otro codigo...


Ahora bien, para tu caso tambien se puede utilizar...

solo tienes que hacer una consulta antes de insertar el Detalle

por ejemplo, creo que seria algo así


Select *
From Detalle_Factura
Where Factura_Producto=iCodigoProducto

If Detalle_Factura.RecordCount > 0 Then
// Aqui informo de que ya esta
Else
// Aqui Inserto el Articulo

Bueno, esto es algo así de memoria, quizas con tus componentes cambie un poco el formato


antes
Salu2:p:D

vmorillos
20-01-2011, 15:54:21
Los codigos de los productos los jalo directamente de la tabla producto, por eso no hay problema. Y respecto de saber si se esta duplicando la llave compuesta (factura, producto) lo que trato es de no sobrecargar a la base de datos (mysql) tal como lo dice Delphius en este hilo : http://www.clubdelphi.com/foros/showthread.php?t=46215

Ademas este es un ejemplo, el código de mi programa es otro. Solo he tomado la parte que no me ejecuta correctamente, que es el ingreso al EXCEPT.

Gracias BlueSteel.

vmorillos
20-01-2011, 16:43:07
Probando y probando he encontrado lo que buscaba


procedure TForm1.Button3Click(Sender: TObject);
var
iCodigoProducto,iCodigoFactura,iCantidad : integer;
fPrecio : Double;
begin
iCodigoProducto:=StrToInt(edProducto.Text);
iCodigoFactura:=StrToInt(edFactura.Text);
iCantidad:=StrToInt(edCantidad.Text);
fPrecio:=StrToFloat(edPrecio.Text);


ZConnection1.StartTransaction;

try
zDetalle.Insert;

zDetalleProdCodigo.Value:=iCodigoProducto;
zDetalleFactCodigo.Value:=iCodigoFactura;
zDetalleCantidad.Value:=iCantidad;
zDetallePrecio.Value:=fPrecio;

zDetalle.Post;
ZConnection1.Commit;
except
//on E: EZSQLException do //<--- Ya no uso esta excepcion
on E:EZDatabaseError do //<--- Esta esta mejor
begin
case E.ErrorCode of
1062: // Este era el codigo que buscaba
begin
ShowMessage('Duplicado'); // El mensaje que yo quiera
end
else
ShowMessage('Error codigo: '+IntToStr(E.ErrorCode)+' - '+E.Message);
end;
ZConnection1.Rollback;
zDetalle.Cancel;

end;

end;

end;


Gracias a todos por su interés.
Saludos