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