[firebase-br] Rollback em Transações ... Insert em um form - Update em Unit Genérica

FORUNS - EMBYTES foruns em embytes.com.br
Seg Out 10 15:29:55 -03 2005


Olá gente!

Por favor esclareçam minha duvida a respeito destas transações.
No caso estou utilizando D7 + DBExpress (SQLQuery + SQLConnection) + 
Firebird.
(não estou utilizando ClientDataSet/DBwares/etc... :))

- tenho que fazer UPDATE em dados na tabela -> usuarios
  (a rotina de update está numa estrutura try/except)
  quando gera exceção, faço rollback em -> usuarios :)
  (frm_principal.conexao.rollback(t_transacao_update_usuario);

- executo o comit em -> usuarios
  (frm_principal.conexao.Commit(t_transacao_update_usuario);)
  caso não gere exceção...
  chamo uma função para INSERT de dados na tabela -> log_seguranca
  (a rotina de inclusão em -> log_segurancao também está em entre 
try/except)

Minhas duvidas :)

Atualizei corretamente -> usuarios
mas gerou exceção em -> log_seguranca
preciso anular o UPDATE em -> usuarios
neste caso, é correto eu fazer
(frm_principal.conexao.rollback(t_transacao_update_usuario);)
mesmo depois de já ter feito o commit e
(atualizado corretamente)?

Ou o correto seria eu apenas executar o sql
(sql_insere_atualiza_usuario.execsql;)
sendo assim só seria feito o commit
caso fosse incluso corretamente em -> log_seguranca,
ao contrario eu faria o rollback em -> usuarios

Mas... se eu fizer assim,
parece que gero um problema pra mim :)

pois eu poderia estar executando
sem fazer o commit em -> usuarios
inserindo corretamente em log_seguranca
e quando eu fosse fazer
o commit em -> usuarios
uma exceção poderia ser gerada ?

Hummm...

Neste caso eu teria que fazer um rollback
no except do UPDATE de -> usuarios :)
e nesta mesma seção (except)
eu faria também um rollback
no -> log_seguranca?
(que tinha sido inserido corretamente :))?

Uaiii... aqui daria um nó :)

Por que eu faço o INSERT em log_seguranca
através de uma unit sem forms.
Criei nela uma funçao genérica que é chamada por N forms.
sendo assim o componente é criado dinamicamente,
recebe os parametros para incluir no log_seguranca
faz o insert (COMMIT) correto
ou gera exceção (faço o rollback)
e depois destruo o componente SQLQuery) :)

...
  finally
    FreeAndNil(sql_log_seguranca);
  end;
...

Gente!
Se estiver correto o trecho do codigo abaixo...
então tudo bem :) estarei feliz :)

*** Acho que escrevi está carta sem muito sentido :)

Mas se eu tiver de que fazer de outra forma...
Podem me dar uma sugestão?

Se eu tiver de voltar a transação do INSERT
no except do UPDATE de -> usuarios
Eu poderia recuperar o numero da transação
do INSERT do log_seguranca e fazer um RollBack ?
Como eu poderia fazer isto ?
(o numero da transação do INSERT em log_seguranca é sempre
t_transacao_insere_log_seguranca.TransactionID  := 1965;)

um trecho da minha rotina de UPDATE em -> usuarios
e uma chamada a inclusao em log_seguranca

  try
    t_transacao_update_usuario.TransactionID  := 1965;
    t_transacao_update_usuario.IsolationLevel := xilREPEATABLEREAD;
    frm_principal.conexao.StartTransaction(t_transacao_update_usuario);
    sql_insere_atualiza_usuario.close;
    sql_insere_atualiza_usuario.sql.clear;
    sql_insere_atualiza_usuario.sql.add('UPDATE USUARIOS ' +
                         'SET ' +
                         'USU_CHAVE = :P_USU_CHAVE, ' +
                         'USU_NOME = :P_USU_NOME, ' +
                         ... BLA BLA BLA
                         'WHERE ' +
                         'USU_CHAVE = :P_USU_CHAVE');

    sql_insere_atualiza_usuario.parambyname('P_USU_CHAVE').Asstring := 
edt_USU_CHAVE.text;
    sql_insere_atualiza_usuario.parambyname('P_USU_NOME').Asstring  := 
AnsiUpperCase(edt_USU_NOME.text);
    sql_insere_atualiza_usuario.execsql;
    frm_principal.conexao.Commit(t_transacao_update_usuario);

    if insere_log_seguranca (edt_USU_CHAVE.Text, 'CADASTRO DE USUARIOS', 
mmo_detalhes.Text) = false Then
    begin
      frm_principal.conexao.rollback(t_transacao_update_usuario);
      exit;
    end;

  // ocorreu um erro ao tentar Atualizar
  except
    On e_erro : exception do
    begin
      ... mostra mensagem de erro
      frm_principal.conexao.rollback(t_transacao_update_usuario);
      exclui_log_temporario(edt_USU_CHAVE.Text);
      exit;
    end;
  end;

um trecho da minha função para INSERT em -> log_seguranca

function insere_log_seguranca (s_reg_chave, s_referencia, s_detalhes : 
string) : boolean;
var
  sql_log_seguranca                : TSQLQuery;
  t_transacao_insere_log_seguranca : TTransactionDesc;
  b_erro                           : boolean;
begin
  // tenta criar o objeto
  try
    b_erro                          := true;
    sql_log_seguranca               := TSQLQuery.Create(nil);
    sql_log_seguranca.sqlconnection := frm_principal.conexao;

    // tenta incluir no log de segurança
    try
      t_transacao_insere_log_seguranca.TransactionID  := 1965;
      t_transacao_insere_log_seguranca.IsolationLevel := xilREPEATABLEREAD;
      
frm_principal.conexao.StartTransaction(t_transacao_insere_log_seguranca);
     
      sql_log_seguranca.close;
      sql_log_seguranca.sql.clear;
      sql_log_seguranca.sql.add('INSERT INTO LOGS_SEGURANCA ' +
                                '(' +
                                'LS_CHAVE, ' +
                                ') ' +
                                'VALUES ' +
                                '(' +
                                ':P_LS_CHAVE, ' +
                                ....... mais paramentros
                                ')');
      sql_log_seguranca.parambyname('P_LS_CHAVE').Asstring       := 
gera_chave;
      .... mais parametros
      sql_log_seguranca.execsql;
      frm_principal.conexao.Commit(t_transacao_insere_log_seguranca);
      ... alguns ajuste em variaveis ....
     
    except
      on e_erro : exception do
      begin
        ... mostra mensagem de erro
        frm_principal.conexao.rollback(t_transacao_insere_log_seguranca);
        exit;
      end;
    end;
  // vamos liberar o objeto sql da memoria
  finally
    FreeAndNil(sql_log_seguranca);
  end;
end;

Obrigado pela força... e ....
desculpem pela carta.
User-BA.




Mais detalhes sobre a lista de discussão lista