Newsgroup: it.comp.lang.delphi
Titolo: Auditing dei record, come memorizzo l'utente?

Ho un datamodule pieno zeppo di componenti TQuery e relativi DSource, ogni
query punta ad una tabella (uso Firebird 1.5), in ognuna di questa tabella
ho previsto 4 campi:
RECORD_CREATO_DA  (testo);
RECORD_DATA_E_ORA (timestamp);
RECORD_MODIFICATO_DA (testo);
RECORD_ULTIMA_MODIFICA (timestamp);
ho creato una variabile 'User' corrispondente al dato di login (nome +
cognome), intendo non l'user interno di Firebird ma un user che pesco da una
tabella Utenti creata appositamente.
Come posso costruire una routine generale che al momento dell'insert o
dell'edit prima dell'evento Post inserisca i 4 dati di cui sopra?
Al momento quello che mi viene in mente sono queste soluzioni:
1) sulla form Main inserire tante n. 4 dbedit per quante sono le tabelle,
soluzione pessima credo
2) scrivere nell'evento BeforePost del componente Query presente nel
Datamodule il codice che inserisce i dati, però lo dovrei fare per ogni
TQuery
3)...
Med

usa i trigger di FB.
Al riguardo, leggi questo articolo:
http://www.ibphoenix.com/main.nfs?a=ibphoenix&l=;IBPHOENIX.PAGES;NAME='ibp_howto10
'
Al 99% fa quello che vuoi fare tu.
Ciao
Duilio

 Al 99% fa quello che vuoi fare tu.
Sě solo che io non uso gli User di Firebird, quelli contenuti nel
security.fdb per intenderci, ma li pesco da una tabella per una ragione che
č legata al dominio della rete. Posso comunque sfruttare questa situazione
secondo te?
Med

>Posso comunque sfruttare questa situazione secondo te?
il problema e' come passare al trigger il tuo nome-utente, che il tuo
programma conosce, ma il trigger no.
Perche' non valuti l'ipotesi di legare il nome-utente di FB al tuo
nome-utente ? 
Un'altra possibilita'  e' quella di allungare ogni singola tabella con
un campo di lavoro USER da riempire ogni volta che fai un
inserimento/modifica/cancellazione. Il trigger potrebbe cosi' leggere
il dato dal campo della tabella che viene modificata.
Se no devi trasferire il codice che scriveresti nei trigger nei
corrispondenti eventi AfterInsert AfterUpdate e AfterDelete delle tue
tabelle e query.
Ciao
Duilio

 Ho un datamodule pieno zeppo di componenti TQuery e relativi DSource,
E vorresti fare una cosa del genere?
Perchè invece non usi una tabella tipo questa:
CREATE TABLE tb_log_journal (
 id                 NUMBER(9)       CONSTRAINT pk_log_journal
                                                 PRIMARY KEY
                                                 CONSTRAINT
ck_log_journal_id
                                                 CHECK (id > 0),
 description                               VARCHAR(4000), // eventuale
descrizione (la uso quando voglio loggare eventuali azioni compiute
dall'utente)
 operator_code                         NUMBER(8)       NOT NULL, // codice
dell'operatore loggato nel programma
 os_user                                    VARCHAR2(255)   NOT NULL,  //
Utente di Sistema
 computer_name                       VARCHAR2(255)   NOT NULL, // nome del
computer
 operation_date                         DATE            NOT NULL, // data
dell'operazione
 operation_type                         NUMBER(1)       NOT NULL // tipo
operazione (1=Insert, 2=Update, 3=Delete)
                                                CONSTRAINT
ck_log_journal_type
                                                CHECK (operation_type IN
(1,2,3,4)),
 involved_table                         VARCHAR2(40)    NOT NULL, // tabella
sulla quale ho eseguito l'operazione
 record_id                                NUMBER(9), // id del record sul
quale ho "lavorato"
 search_key                             VARCHAR2(40), // eventuale chiave di
ricerca
 fields_list                                CLOB, // lista dei nomi dei
campi
 record_new_detail                 CLOB, // I valori di prima
 record_old_detail                  CLOB // i valori di dopo
 )
Per far ciò, ho modificato il componente TQuery e TDataSet.... In questo
modo non devo stare lì a sbattere ogni volta che aggiungo una nuova tabella
o una nuova form di Data Entry..... Mi basta usare i componenti modificati e
il gioco è fatto.... per ognuno di loro ho aggiunto una proprieta ActiveLog
(Boolean) e, per quei dati che voglio loggare..... l'unico sforzo che devo
fare è quello di impostare a True detta Proprietà.
Quando mi interessa sapere qualcosa, cosa è successo in alcune tabelle......
interrogo la tabella  tb_log_journal.
Io ti sconsiglierei vivamente di modificarti tutte le tabelle, aggiungendo
per ognuna di loro 4 campi... (scusami ma per me è pazzesco...).... boh!!!
Magari non ne puoi fare a meno...
Spero di esserti stato di aiuto...
Ciao,
  Alessandro Storniolo

 ogni TQuery
Al posto di questa puoi semplicemente mettere un TLoggerQry in cui fai
l'override di DoBeforePost:
TLoggerQry = class (TIBQuery)
protected
  procedure DoBeforePost; override;
end;
Al suo interno valorizzi i 4 campi con i dati dell'utente corrente.
procedure TLoggerQry.DoBeforePost;
begin
  if IsNewRecord() then begin
  ...
  else begin
    FieldByName('RECORD_MODIFICATO_DA').AsString := CurrentLoggedUser;
    FieldByName('RECORD_ULTIMA_MODIFICA').AsDateTime := Now;
  end;
  inherited;
end;
Oppure (se hai bisogno di mantenere tutte le modifiche) fai una tabella
a parte con una struttura tipo
TableName | RecID | User | Time | Operation
che viene riempita con uno statement appositamente costruito in un
DoAfterPost.
Saluti
Paolo Arosio

 tabelle e query.
Thanks
Med

 Magari non ne puoi fare a meno...
Oggi stavo provando proprio questa soluzione grazie per il consiglio. Bye
Med

 a parte con una struttura tipo
 proverň anche questa soluzione seguendo l'ottimo suggerimento di A.
Storniolo piů sopra. Thanks
Med

Nel tuo DataModule puoi creare una procedura
procedure Form.Query1BeforePost(DataSet: TDataSet);
begin
   case DataSet.State of
     dsInsert: begin
                     DataSet.FieldByName('RECORD_CREATO_DA').Value := User;
                     DataSet.FieldByName('RECORD_DATA_E_ORA').Value := date;
                   end;
     dsInsert: begin
                     DataSet.FieldByName('RECORD_MODIFICATO_DA').Value :=
User;
                     DataSet.FieldByName('RECORD_ULTIMA_MODIFICA').Value :=
date;
                   end;
   end;
end;
e la associ all'evento BeforePost delle Query che ti interessano
Ciao
Nicola