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

Anticlei Scheid cleischeid em yahoo.com.br
Seg Out 10 16:09:23 -03 2005


Depois que executou o commit não tem mais volta.
Sugestão: Coloque as duas atualizações dentro do mesmo bloco try/except já 
que são dependentes uma da outra:

  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;
    // a função insere_log_seguranca deve levantar uma exceção caso ocorra 
algum erro (raise)
    insere_log_seguranca (edt_USU_CHAVE.Text, 'CADASTRO DE USUARIOS', 
mmo_detalhes.Text);

    //aqui ocorre o commit do update de usuários e do insert no log
    //se conseguir executar esta linha quer dizer que não houve exceção, 
logo pode dar o commit
    frm_principal.conexao.commit(t_transacao_update_usuario);

except
    //depois do try e em qualquer ponto até a palavra chave except se 
ocorrer alguma exceção a próxima linha será             //executada fazendo 
um rollback tanto do update de usuários, quanto do insert no log
    //logo você não precisará programando um "estorno" das suas atualizações 
e/ou inserções
    frm_principal.conexao.rollback(t_transacao_update_usuario);
end;

Observação: o nome da transação que você criou sugere uma tabela, mas quando 
você executa um commit ou rollback, isso é feito no nível de transação do 
banco e não no nível de tabela, logo todas as instruções SQL executadas 
dentro da transação serão "commitadas" ou "rollbackadas" :) (entenda-se 
dentro da transação as instruções que apontarem para o SQLConnection 
(frm_principal.conexao) e que estiverem depois do StartTransaction e antes 
do commit ou rollback.

Inté e boa sorte.

----- Original Message ----- 
From: "FORUNS - EMBYTES" <foruns em embytes.com.br>
To: "FireBase" <lista em firebase.com.br>
Sent: Monday, October 10, 2005 3:29 PM
Subject: [firebase-br] Rollback em Transações ... Insert em um form - Update 
em Unit Genérica


> 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.
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
> Para editar sua configuração na lista, use o endereço 
> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
>
> -- 
> No virus found in this incoming message.
> Checked by AVG Anti-Virus.
> Version: 7.0.344 / Virus Database: 267.11.14/127 - Release Date: 
> 10/10/2005
> 





Mais detalhes sobre a lista de discussão lista