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)
-   -   Transaciones IBX (https://www.clubdelphi.com/foros/showthread.php?t=23994)

Loviedo 04-08-2005 16:19:37

Transaciones IBX
 
Tengo dos tablas (master/detail).
Utilizo Delphi7,Firebird 1.5, e IBQuery.
Mi problema es que no puedo insertar más de un registro(Detail),
porque no se confirman los datos hasta que realizo el Commit,
y es entónces cuando se incrementa el código familia.
No puedo individualizarlos porque va todo dentro de la misma
transación. Pienso en una transación anidada, pero no se como
hacerla y si es permitida.

Código Delphi [-]
procedure TFFicha.aceptarClick(Sender: TObject);
var
  codigoficha: integer;
begin
  if not (FDM.IBT1.InTransaction) then
    FDM.IBT1.StartTransaction;
  try
   codigoficha := FDM.codigosFICHA.AsInteger;
   FDM.PFICHA.StoredProcName:= 'ALTAFICHA';
   FDM.PFICHA.Parambyname('mcod').asinteger:=codigoficha;
   FDM.PFICHA.Parambyname('mnombre').asstring:=uppercase(nombre.text);
   FDM.PFICHA.Parambyname('mapell').asstring:=uppercase(apellidos.Text);
   FDM.PFICHA.Parambyname('mfecha').asdatetime:=fecha.date;
   // Guarda familia
   if not FDM.FamiliaT.IsEmpty then
     begin
       FDM.FamiliaT.First;
       while not FDM.FamiliaT.Eof do
         begin
           FDM.PFamilia.StoredProcName:='P_ALTAFAMILIA';
           FDM.PFamilia.ParamByName('mCod').value := codigoficha;
           FDM.PFamilia.ParamByName('mCodf').value:= FDM.CodigosFAMILIA.AsInteger;
           FDM.PFamilia.ParamByName('mNom').value:= FDM.FamiliaTNombre.text;
           FDM.PFamilia.ParamByName('mApell').value := FDM.FamiliaTApellidos;
           FDM.PFamilia.ExecProc;
           FDM.Incrementa.StoredProcName:='P_INCFAMILIA';//Incrementa el código familia
           FDM.Incrementa.ExecProc;
           FDM.FamiliaT.Next;
         end;
     end;
   FDM.IBT1.Commit;
 except
   FDM.IBT1.Rollback;
 end;
end;
saludos y Gracias anticipadas.

kalimero 04-08-2005 16:41:20

Hola.

¿Podrias publicar el codigo del procedimiento almacenado 'P_INCFAMILIA?

Saludos

rastafarey 04-08-2005 16:49:30

Resp
 
No entiendo cual es tu problema. La tansaccion no termina hasta hacer commit o rollback.

Si tienes una integridada referencial entre master y detalles exister el registro relacionado con el master.

Primero ten cuidado con el procedimiento qu eincremnte el codigo. Me imagino que usas un generador ya que este no respeta las transacciones y asi te evitas codigos duplicados en un hanbiente multiusuario.

Te doy un ejemplo de como puedes hacer.

Master 1:
Lees el codigo del master
Asiganas los dados y ejecutas el master

Detalles 1 master 1
Asiganas los dados y ejecutas el detalle
Detalles 2 master 1
Asiganas los dados y ejecutas el detalle
y asi sucesivamente.

Igual para el master 2 y sus detalles.

Luego de todo esto puedes hacer el commit.

Pero tambien puedes hacer el commit despues de insertar el ultimo detalle de un master.
Asi puedes insertar todos los detalles que quieres a un master.

Pero una vez mas te recuerdo lo del control d etransacciones ay que si el codigo no lo controlar con un generador te puede dar un error de bloqueo muerto o conflitos de calves primarias.

Espero te sirva de ayuda.

Loviedo 04-08-2005 17:38:49

Este es el procedimiento

Código Delphi [-]
Procedimiento P_INCFAMILIA
EGIN
  UPDATE codigos SET familia=familia+1;
END

El problema es que en el bucle, no se incrementa el 'FDM.CodigosFAMILIA.AsInteger' y me sale
violación clave primaria al insertar el siguiente registro.
'FDM.CodigosFAMILIA.AsInteger' se refresca después del commit.
Gracias.

kalimero 04-08-2005 17:55:21

Hola.
En mi opinion deberias llevar el incremento del Codfamilia fuera del procedimiento.Me refiero a que lo Incrementes tu por codigo

Saludos

rastafarey 04-08-2005 18:32:22

resp
 
Usa un generador.

Si el generador se llama gen_Id_familia

Haces Un select
Código SQL [-]
Select Gen_id(gen_Id_familia, 0) From rdb$datbase
Select Gen_id(gen_Id_familia, 1) From rdb$datbase
El primero te saca el valor actual
y el otro incrmente en uno.

y el error te ocurre ya que el valor se esta incrementando dentro del procedimiento y no fuera como te didjeron anteriormente.

Loviedo 04-08-2005 18:55:29

Muchas gracias por las respuestas.
Me inclinaré por uno de los métodos indicados.
Saludos.

AGAG4 04-08-2005 21:22:38

Recomiendo
 
Te Recomiendo usar la propiedad CachedUpdates en los IBDataSet sobre la realción maestro detalle que comentas, cuando guardes en vez de usar el POST lo cambias por CachedUpdates, y cuando vayas a aceptar la transacción primero Grabas el Detalle y posteriormente el Maestro, si me preguntas porque, te respondo asi me funcionó, que debería de ser primero el Maestro y después el Detalle y por último Aceptas la transacción....

Saludos....

Loviedo 05-08-2005 00:20:37

¡ ya lo conseguí !. No se si es muy ortodoxo pero...

Código Delphi [-]
   if not FDM.FamiliaT.IsEmpty then
     begin
       FDM.FamiliaT.First;
       while not FDM.FamiliaT.Eof do
         begin
           FDM.PFamilia.StoredProcName:='P_ALTAFAMILIA';
           FDM.PFamilia.ParamByName('mCod').value := codigoficha;
           FDM.PFamilia.ParamByName('mCodf').value:= FDM.CodigosFAMILIA.AsInteger;
           FDM.PFamilia.ParamByName('mNom').value:= FDM.FamiliaTNombre.text;
           FDM.PFamilia.ParamByName('mApell').value := FDM.FamiliaTApellidos.text;
           FDM.PFamilia.ParamByName('mEdad').value := FDM.FamiliaEDAD.asinteger;
           FDM.PFamilia.ParamByName('mDoc').value := FDM.FamiliaTDocumentos.asinteger;
           FDM.PFamilia.ParamByName('mSit').value := FDM.FamiliaTSituacion.asinteger;
           FDM.PFamilia.ParamByName('mParent').value := FDM.FamiliaTParentesco.Text;
           FDM.PFamilia.ExecProc;
           FDM.Incrementa.StoredProcName:='P_INCFAMILIA';
           FDM.Incrementa.ExecProc;
           FDM.codigos.Close;
           FDM.codigos.Open;
           FDM.FamiliaT.Next;
         end;
     end;
Gracias por todo.

rastafarey 05-08-2005 20:40:22

Resp
 
Recuerda que en un entorno mmulti usuraio si no usas generadores para el id primario te puede dar bloques muertos. o Conflitos de claves devido al control transacional.

Loviedo 06-08-2005 02:10:00

Gracias por la ayuda. Usaré generadores. Lo que ocurre es que el tema refresh
no me funciona, y no he leido en el foro algo definitivo.
Saludos.


La franja horaria es GMT +2. Ahora son las 06:53:32.

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