Newsgroup: it.comp.lang.delphi
Titolo: [D6-ADO-LUNGO] Gestione delle transazioni

Ciao a tutti,
sto sbattendo la testa contro un pezzo di codice contenente delle
transazioni.
In sostanza:
- ho una tabella anagrafica dove modifico/inserisco i record;
- in una tabella di contatori, per ogni record inserito incremento un
numero di contatore;
- se viene sollevata qualunque eccezione il contatore non deve essere
incrementato.
L'idea di codice è questa:
Evento ***BeforePost***
Attivo le transazioni e, in caso di inserimento di un nuovo record,
apro la tabella dei contatori, assegno il nuovo valore al codice, ed
incremento il contatore.
In Caso di errore sollevo un'eccezione, per ogni eccezione effettuo il
Rollback.
procedure TdmStock.tbAnagraficaBaseBeforePost(DataSet: TDataSet);
begin
 tbAnagraficaBase.Connection.BeginTrans;
  try
   { Per i nuovi record calcola il codice anagrafico }
  if tbAnagraficaBase.State = dsInsert then begin
   tbContatori.Active := True;
   tbContatori.Locate('ctt_codice', 'ANA', [loCaseInsensitive]);
   fldAnaCodice.Value := fldCttUltimo.Value + 1;
   tbContatori.Edit;
     fldCttUltimo.Value := fldCttUltimo.Value + 1;
     tbContatori.Post;
      tbContatori.Active := False;
   end;
    { Verifica dei campi obbligatori }
    if fldAnaFornitore.Value then begin
     if Trim(fldAnaCodStock.Value) = '' then
       raise Exception.Create(MSG_ANA_001);
    end;
  except
   tbAnagraficaBase.Connection.RollbackTrans;
    raise;
  end;
end;
Evento *** PostErrorr ***
Stando alla documentazione, questo evento viene sollevato per ogni
eccezione non gestita direttamente dagli altri,
quindi effettuo RollBack
procedure TdmStock.tbAnagraficaBasePostError(DataSet: TDataSet; E:
EDatabaseError; var Action: TDataAction);
begin
 tbAnagraficaBase.Connection.RollbackTrans;
end;
Evento *** AfterPost ***
Effettuo il Commit della transazione.
procedure TdmStock.tbAnagraficaBaseAfterPost(DataSet: TDataSet);
begin
 tbAnagraficaBase.Connection.CommitTrans;
end;
In sostanza, il problema è che mi ritrovo - per ogni record inserito
nuovo - il contatore incrementato pur effettuando il RollBac, mentre a
mio avviso non dovrebbe esserlo.
Gianluca.

Evento ***BeforePost***
Gianluca, ho letto velocemente il tuo post, sta di fatto che anche io uso le
trasazioni con ado, e il mio consiglio e' di NON legarle agli eventi del
dataset (in quanto asincroni) ma ad un pulsante che scatena in serie tutte le
scritture del caso.
try
   BeginTransaction
   ...
 
tabella1.post
   funzione()
 
tabella2.post
   tabella3.edit
      .....
 
tabella3.post
   Committransaction
except on e : exception dobegin
   rollbacktransaction
   end;
end;
Non so se questo dirty pseudocodice possa fare al caso tuo, ma io ho cercato
di standardizzare questo sistema nei miei porgrammi, e mi sono sempre trovato
bene.
Ciao!
-- 
Morde. 
(morde at programmer dot net)

"Morde" ha scritto nel messaggio

Grazie per il suggerimento: ora il codice è molto piu' pulito.
Il problema però era di tutt'altro genere: in sostanza - trovandosi
questo codice in una DLL - alla funzione chiamata passo un puntatore
all'oggetto ADOConnection che uso nell'eseguibile principale e lo
imposto come property Connection della mia ADOTable. Avevo
semplicemente dimenticato (AAARRRRGGH!) di impostarlo anche per la
tabella dei contatori. Quindi quest'ultima era legata alla connessione
standard che uso a design e di conseguenza non era sotto transaction.
Gianluca.