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 Temas de Hoy

Conexión con bases de datos

 
 
Herramientas Buscar en Tema Desplegado
  #4  
Antiguo 15-11-2003
Lmas Lmas is offline
Miembro
 
Registrado: jul 2003
Ubicación: España
Posts: 27
Poder: 0
Lmas Va por buen camino
Hola mgaray.

Sin duda alguna, la mejor forma de resolver el problema que planteas de los usuarios es el uso de campos autonuméricos; y en cuanto a los problemas de inserciones y modificaciones en relaciones maestro-detalle...

Uns estructura típica de relación maestro-detalle con una tabla de Facturas y otra de FacturasDetalle:
Código:
Facturas
(
  id  -  Autonumérico
  ClienteId - Entero largo (Cliente de quien es la factura)
   ...
   resto de campos
);

FacturasDetalle
(
  id - Autonumérico
  FacturaId - Entero largo (A qué factura de la tabla anterior pertenece este detalle)
  ...
  resto de campos
);
y para mostrar estas tablas tienes dos vistas (o consultas en Access) vwFacturas y vwFacturasDetalle en las que muestras el nombre del cliente, en vez de ClienteId en la primera, y haces algo parecido con la segunda.

En Delphi tendrás dos TADODataset o similar, dsFacturas cuyo origen de datos sea vwFacturas y, dsFacturasDetalle cuyo origen sea vwFacturasDetalle.

Entonces, debes configurar las siguientes propiedades de los Recordset para que al hacer las inserciones en la tabla maestra, automáticamente ADO actualice el campo incremental del registro recién insertado (sólo el nuevo registro, y no toda la tabla), para así poder añadir registros detalle.

En el evento BeforePost de dsFacturas (yo lo pongo en este evento, aunque si no hacer posteriores Requerys o cosas similares, supongo que podría ponerse en el AfterOpen)

Código:
  dsFacturas.Properties['Unique Table'].Value := 'Facturas';
  dsFacturas.Properties['Update Criteria'].Value := adCriteriaUpdCols;
  dsFacturas.Properties['Update Resync'].Value := adResyncAll;
  dsFacturas.Properties['Resync Command'].Value := 'SELECT * FROM vwFacturas WHERE vwFacturas.id = ?';

  y para los detalle:


  dsFacturasDetalle.Properties['Unique Table'].Value := 'FacturasDetalle';
  dsFacturasDetalle.Properties['Update Criteria'].Value := adCriteriaUpdCols;
  dsFacturasDetalle.Properties['Update Resync'].Value := adResyncAll;
  dsFacturasDetalle.Properties['Resync Command'].Value := 'SELECT * FROM vwFacturasDetalle WHERE vwFacturasDetalle.id = ?';
Unique Table, indica que sólo se actualice esa tabla de las que forman la vista y ADO no intente actualizar las tablas relacionadas.
Update Criteria, indica el criterio de comparación de las columnas en la actualización (la clave primeria, timestamp, etc... Los posibles valores están en ADOInt.pas)
Update Resync, indica cuando sincronizar la tabla. Los posibles valores también están en ADOInt.
Resync Command, es la instrucción SQL que ADO ejecutará para sincronizar la tabla. En ella ADO sustituye el "?" por la clave primaria de la tabla; en este caso, el campo autoincremental.

Para hacerlo como te indica jachguate en un todo o nada mediante transacciones:
Código:
  Conexion.BeginTrans;
  try
    dsFacturas.Append;
    tbFacturasClienteId.AsInteger := XXXX;
    dsFacturas.Post;
    // Primer detalle
    dsFacturasDetalle.Append;
    tbFacturasDetalleFacturaId.AsInteger := tbFacturasId.AsInteger;
    dsFacturasDetalle.Post;
    // Segundo detalle
    dsFacturasDetalle.Append;
    tbFacturasDetalleFacturaId.AsInteger := tbFacturasId.AsInteger;
    dsFacturasDetalle.Post;
    Conexion.CommitTrans;
  except
    Conexion.RollbackTrans;
  end;
La propiedad LockType de los Datasets debe ser ltOptimistic.

El quid de la cuestión es que ADO automáticamente, tras "dsFacturas.Post", lanza un "SELECT @@identity" que devuelve el valor del último campo incremental que se haya generado en la conexión y tras ese comando lanza el que se haya puesto en la propiedad "Resync Command" del Recordset, sustituyendo el "?" por el valor que acaba de obtener de la consulta anterior. De esta forma en "tbFacturasDetalleFacturaId.AsInteger := tbFacturasId.AsInteger" se está dando al registro detalle la clave primaria con la que está relacionada. Todo este proceso se puede ver con el SQL Profiler del SQL Server.

Lo anterior funciona a partir de SQL Server 2000 y de Access 2000, en versiones anteriores no (no recuerdo exactamente si era necesario también el MDAC 2.5 o superior, lo puedes consultar el el MSDN de Microsoft).

Bueno, vale ya de tanto rollo.

SalU2
__________________
Una cosa es una cosa, y otra cosa es otra cosa...

Última edición por Lmas fecha: 15-11-2003 a las 14:05:50.
Responder Con Cita
 



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


La franja horaria es GMT +2. Ahora son las 15:57:36.


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