Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-08-2017
wilcg wilcg is offline
Miembro
 
Registrado: abr 2014
Posts: 107
Poder: 10
wilcg Va por buen camino
Forma correcta de guardar un Maestro-Detalle

Amigos del foro un cordial saludo, necesito su ayuda con respecto a este tema de como es la manera mas correcta de guardar datos de un maestro-detalle
en la base de datos. Utilizo componentes UNIDAC y base de datos POSTGRESQL.

Tengo un ClientDataset en donde hay datos en memoria, lo que estoy haciendo es lo siguiente:

Código Delphi [-]
with UniQuery1 do
 begin

   try   
     // MAESTRO
     Close;
     SQL.Clear;
     SQL.Add('INSERT INTO factura ( '+
        ' id_factura, fecha_emision, id_proveedor, id_comprobante, observaciones ) VALUES ( '+
        ' :id_factura, :fecha_emision, :id_proveedor, :id_comprobante, bservaciones )
        );
     ParamByName('id_factura').Value         := iDFactura;
     ParamByName('fecha_emision').Value      := FormatDateTime( F_FF, edtFEmision.Date );
     ParamByName('id_proveedor').Value       := edtProveedor.Value;
     ParamByName('id_comprobante').Value     := edtComprobante.Value;
     ParamByName('observaciones').AsString   := edtObservaciones.Lines.Text;
     ExecSQL;

     // DETALLE
     if (ClientDataset1.Active) then
     begin
        Marca := ClientDataset1.Bookmark;

        ClientDataset1.First;
        while Not ClientDataset1.Eof do
        begin
          Close;
          SQL.Clear;
          SQL.Add('INSERT INTO detalles ( '+
            ' id_factura, id_producto, id_medida, cantidad, costo_unidad, precio_venta ) VALUES ( '+
            ' :id_factura, :id_producto, :id_medida, :cantidad, :costo_unidad, recio_venta )'
            );
          ParamByName('id_factura').Value          := iDFactura; 
          ParamByName('id_producto').Value         := ClientDataset1.FieldByName('id_producto').Value;
          ParamByName('id_medida').Value           := ClientDataset1.FieldByName('id_medida').Value;
          ParamByName('cantidad').AsFloat          := ClientDataset1.FieldByName('cantidad').AsFloat;
          ParamByName('costo_unidad').AsFloat      := ClientDataset1.FieldByName('costo_unidad').AsFloat;
          ParamByName('precio_venta').AsFloat      := ClientDataset1.FieldByName('precio_venta').AsFloat;
          ExecSQL;

        ClientDataset1.Next;
      end;

      ClientDataset1.Bookmark := Marca;
      Application.MessageBox(pchar(  'Registro creado correctamente.'),pchar(' Mensaje'),
            MB_OK+MB_ICONINFORMATION);
   except
     Application.MessageBox(pchar(  'Surgieron errores durante la creación del registro.'),
            pchar(' Mensaje'),MB_OK+MB_ICONERROR);

   end;

 end;

Si me pueden ayudar con este tema, o un ejemplo mucho mas correcto de realizar este tipo de operaciones.
Responder Con Cita
  #2  
Antiguo 08-08-2017
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.732
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Yo persobalmente haría dos bloques try...except.
En el caso de que falle el segundo, podría ser que desearas borrar la cabecera para no dejar restos o cosas incompletas.
Además, si recorres un DataSet que estás mostrando deberías deshabilitarlo antes y habilitarlo después. Todo esto dentro de un bloque try...finally.
Finalmente,, y solo por estética, prefiero crear los SQL con varios SQL.Add().

Te dejo a continuación mi versión...

Código Delphi [-]
with UniQuery1 do
begin
  try 
    // Al principio estoy segudo de que no hay errores
    HayError := False;
    
    // MAESTRO
    Close;
    SQL.Clear;
    SQL.Add(' INSERT INTO factura ( ');
    SQL.Add(' id_factura, fecha_emision, id_proveedor, id_comprobante, observaciones ) ');
    SQL.Add(' VALUES ( ');
    SQL.Add(' :id_factura, :fecha_emision, :id_proveedor, :id_comprobante, bservaciones ) ');
    ParamByName('id_factura').Value         := iDFactura;
    ParamByName('fecha_emision').Value      := FormatDateTime( F_FF, edtFEmision.Date );
    ParamByName('id_proveedor').Value       := edtProveedor.Value;
    ParamByName('id_comprobante').Value     := edtComprobante.Value;
    ParamByName('observaciones').AsString   := edtObservaciones.Lines.Text;
    ExecSQL;
  except
    on E:Exception do
    begin
      HayError := True;
      Application.MessageBox(pchar('Surgieron errores durante la creación del registro cabecera.' + #13#10 + E.Message),
      pchar(' Mensaje'),MB_OK+MB_ICONERROR);
    end;
  end;

  // Si no hubo errores al crear la cabecera sigo con el detalle
  if (not HayError) then
  begin
    try
      // DETALLE
      Marca := ClientDataset1.Bookmark;
      
      // Deshabilito refrescos del DataSet
      ClientDataset1.DisableControls;
      try
        if (ClientDataset1.Active) then
        begin
          ClientDataset1.First;
          while Not ClientDataset1.Eof do
          begin
            Close;
            SQL.Clear;
            SQL.Add(' INSERT INTO detalles ( ');
            SQL.Add(' id_factura, id_producto, id_medida, cantidad, costo_unidad, precio_venta ) ');
            SQL.Add(' VALUES (  ');
            SQL.Add(' :id_factura, :id_producto, :id_medida, :cantidad, :costo_unidad, recio_venta ) ');
            ParamByName('id_factura').Value          := iDFactura; 
            ParamByName('id_producto').Value         := ClientDataset1.FieldByName('id_producto').Value;
            ParamByName('id_medida').Value           := ClientDataset1.FieldByName('id_medida').Value;
            ParamByName('cantidad').AsFloat          := ClientDataset1.FieldByName('cantidad').AsFloat;
            ParamByName('costo_unidad').AsFloat      := ClientDataset1.FieldByName('costo_unidad').AsFloat;
            ParamByName('precio_venta').AsFloat      := ClientDataset1.FieldByName('precio_venta').AsFloat;
            ExecSQL;

            ClientDataset1.Next;
          end;
        end;
        ClientDataset1.Bookmark := Marca;
      finally
        // Vuelvo a habilitar refrescos del DataSet
        ClientDataset1.EnableControls;
      end;

      Application.MessageBox(pchar(  'Registro creado correctamente.'),pchar(' Mensaje'),
      MB_OK+MB_ICONINFORMATION);
    except
      on E:Exception do
      begin
        Application.MessageBox(pchar(  'Surgieron errores durante la creación del registro.'  + #13#10 + E.Message),
        pchar(' Mensaje'),MB_OK+MB_ICONERROR);
      end;
    end;
  end;
end;
Responder Con Cita
  #3  
Antiguo 08-08-2017
bitbow bitbow is offline
Miembro
 
Registrado: jul 2006
Posts: 366
Poder: 18
bitbow Va camino a la fama
Lo ideal si tienes pensado manejar un correcto control de errores, seria usar transacciones con lo cual si hay algun error solo haces rollback y listo.

Saludos.
__________________
¡Ni como ayudarte Niño!!
bitbow
Responder Con Cita
  #4  
Antiguo 09-08-2017
wilcg wilcg is offline
Miembro
 
Registrado: abr 2014
Posts: 107
Poder: 10
wilcg Va por buen camino
Gracias amigos por responder, es de mucha ayuda sus respuestas.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
forma correcta de acceder y guardar en firebird con ibx anubis Lazarus, FreePascal, Kylix, etc. 16 01-03-2017 18:05:54
forma de programar no se si es la correcta ? gulder MySQL 4 05-04-2016 18:49:51
Maestro/Detalle - Forma correcta de dar Alta un registro pape19 Varios 7 16-06-2014 15:40:17
Guardar Maestro-Detalle (Problema super comun) sonjeux Conexión con bases de datos 2 19-02-2007 19:28:29
Cual es la Forma Correcta de Guardar Texto en un IbDataset con TcpServer???? AGAG4 Varios 0 10-12-2004 23:14:41


La franja horaria es GMT +2. Ahora son las 04:34:37.


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