TDBPlanner y bases de datos transaccionales
Artículo por Club Developers · 12 marzo 2006
2891 vistas
El TDBPlanner es uno de los mejores componentes para la realización de "agendas" estilo Outlook o Sunbird, pero a la que lo enlazamos con una base de datos transaccional como Firebird, nos encontramos con la sorpresa de no saber dónde hacer el commit de la transacción.
Póngamonos en situación:
Accedemos a los datos mediante TClientDataSet + TDataSetProvider + FIBPlus (TpFIBDataSet)
Mostramos los datos en un TDBPlanner + TDBDaySource
Problema:
Si revisamos los eventos del TDBPlanner y del TDBDaySource, vemos que no hay ningún evento que se "dispare" después de la insercción del registro, por lo que no sabemos dónde hacer el commit de la transacción.
Solución:
Si miramos el código fuente del componente TDBDaySource, vemos que el post del registro se realiza en el método público WriteDBItem, pero sin disparar ningún evento.
Lo que vamos ha realizar es reescribir este método y hacer que dispare un evento. Para ello, vamos a usar la técnica de las clases interpuestas que Marteens explica muy bien en este artÃculo y, asÃ, evitar la instalación de nuevos componentes en nuestra paleta
Veamos cómo lo realizamos:
Después de la declaración de las uses (y antes de la declaración del formulario) definimos nuestra clase interpuesta
y ahora la implementamos
Si queremos que después del "post" se haga el "commit", sólo tendremos que programar el nuevo evento del TDBDaySource
Póngamonos en situación:
Accedemos a los datos mediante TClientDataSet + TDataSetProvider + FIBPlus (TpFIBDataSet)
Mostramos los datos en un TDBPlanner + TDBDaySource
Problema:
Si revisamos los eventos del TDBPlanner y del TDBDaySource, vemos que no hay ningún evento que se "dispare" después de la insercción del registro, por lo que no sabemos dónde hacer el commit de la transacción.
Solución:
Si miramos el código fuente del componente TDBDaySource, vemos que el post del registro se realiza en el método público WriteDBItem, pero sin disparar ningún evento.
Lo que vamos ha realizar es reescribir este método y hacer que dispare un evento. Para ello, vamos a usar la técnica de las clases interpuestas que Marteens explica muy bien en este artÃculo y, asÃ, evitar la instalación de nuevos componentes en nuestra paleta
Veamos cómo lo realizamos:
Después de la declaración de las uses (y antes de la declaración del formulario) definimos nuestra clase interpuesta
delphi
interface uses  ...., DBPlanner,.....; type  // definimos el evento  TAfterEdit = procedure of object;  // definimos la clase  TDBDaySource = class(DBPlanner.TDBDaySource)  private   FAfterEdit: TAfterEdit;  public   procedure WriteDBItem; override; // reescribimos el método deseado   property AfterEdit: TAfterEdit read FAfterEdit write FAfterEdit; // declaramos el evento  end;
y ahora la implementamos
delphi
procedure TDBDaySource.WriteDBItem; begin  inherited;  if Assigned(FAfterEdit) then FAfterEdit; end;
Si queremos que después del "post" se haga el "commit", sólo tendremos que programar el nuevo evento del TDBDaySource
delphi
 TForm1 = class(TForm)  private   // definimos el evento del TDBDaySource (ya que no se visualiza en el Inspector de Objetos)   procedure DBDaySource1AfterEdit;  protected  public   // redefinimos el contrustor de la clase (también podrÃamos usar el evento OnCreate)   constructor Create(aOwner: TComponent); override;  end; ... implementation constructor TForm1.Create(aOwner: TComponent); begin  inherited;  // asignamos nuestro procedimiento al evento del TDBDaySource  DBDaySource1.AfterEdit := DBDaySource1AfterEdit; end procedure TForm1.DBDaySource1AfterEdit; var  Err: integer; begin  // si no hay transacción activa, la activamos  if not pFIBDataSet1.Transaction.InTransaction then   pFIBDataSet1.Transaction.StartTransaction;  // realizamos ApplyUpdates del ClientDataSet  Err := 0;  if ClientDataSet1.Active then   Err := ClientDataSet1.ApplyUpdates(0);  // si no hay errores....  if Err = 0 then  begin   // hacemos commit de la transacción   pFIBDataSet1.Transaction.Commit;   // refrescamos datos del ClientDataSet   if ClientDataSet1.Active then ClientDataSet1.Refresh;   // sincronizamos el TDBDaySource   DBDaySource1.SynchDBItems;  end; end;