[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