TDBPlanner y bases de datos transaccionales

2788 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



delphi
  1. interface
  2.  
  3. uses
  4.   ...., DBPlanner,.....;
  5.  
  6. type
  7.   // definimos el evento
  8.   TAfterEdit = procedure of object;
  9.  
  10.   // definimos la clase
  11.   TDBDaySource = class(DBPlanner.TDBDaySource)
  12.   private
  13.     FAfterEdit: TAfterEdit;
  14.   public
  15.     procedure WriteDBItem; override;  // reescribimos el método deseado
  16.  
  17.     property AfterEdit: TAfterEdit read FAfterEdit write FAfterEdit;  // declaramos el evento
  18.   end;



y ahora la implementamos



delphi
  1. procedure TDBDaySource.WriteDBItem;
  2. begin
  3.   inherited;
  4.  
  5.   if Assigned(FAfterEdit) then FAfterEdit;
  6. end;



Si queremos que después del "post" se haga el "commit", sólo tendremos que programar el nuevo evento del TDBDaySource



delphi
  1.   TForm1 = class(TForm)
  2.   private
  3.     // definimos el evento del TDBDaySource (ya que no se visualiza en el Inspector de Objetos)
  4.     procedure DBDaySource1AfterEdit;
  5.   protected
  6.   public
  7.     // redefinimos el contrustor de la clase (también podrÃamos usar el evento OnCreate)
  8.     constructor Create(aOwner: TComponent); override;
  9.   end;
  10.  
  11. ...
  12.  
  13. implementation
  14.  
  15. constructor TForm1.Create(aOwner: TComponent);
  16. begin
  17.   inherited;
  18.  
  19.   // asignamos nuestro procedimiento al evento del TDBDaySource
  20.   DBDaySource1.AfterEdit := DBDaySource1AfterEdit;
  21. end
  22.  
  23. procedure TForm1.DBDaySource1AfterEdit;
  24. var
  25.   Err: integer;
  26. begin
  27.   // si no hay transacción activa, la activamos
  28.   if not pFIBDataSet1.Transaction.InTransaction then
  29.     pFIBDataSet1.Transaction.StartTransaction;
  30.  
  31.   // realizamos ApplyUpdates del ClientDataSet
  32.   Err := 0;
  33.   if ClientDataSet1.Active then
  34.     Err := ClientDataSet1.ApplyUpdates(0);
  35.  
  36.   // si no hay errores....
  37.   if Err = 0 then
  38.   begin
  39.     // hacemos commit de la transacción
  40.     pFIBDataSet1.Transaction.Commit;
  41.     // refrescamos datos del ClientDataSet
  42.     if ClientDataSet1.Active then ClientDataSet1.Refresh;
  43.     // sincronizamos el TDBDaySource
  44.     DBDaySource1.SynchDBItems;
  45.   end;
  46. end;