Fórum Problemas com Commit e RollBack #403951
28/06/2011
0
Estou com um problema que esta me enchendo o saco.
estou executando três procedimentos, da seguinte forma:
1 if dm.ibTR.InTransaction then
2 dm.ibTR.Commit;
3 dm.ibTR.StartTransaction;
4 try
5 UpDateContrato;
6 UpDateCONXIMO;
7 UpDateImovel;
8 except
9 on e:EIBError do begin
10 dm.ibTR.Rollback;
11 MessageDlg('Menssagem: '+inttostr(E.SQLCode)+' '+E.Message+#13,mtError,[mbOK],0);
12 CancelarClick(Self);
13 Exit;
14 end;
15 end;
16 dm.ibTR.Commit;
17 CancelarClick(Self);
a idéia é que quando se algum desses procedimentos der um erro não seja gravado nada no banco, ou seja, dá um Rollback, linha 10. E se der tudo certo, Commit, linha 16. Blz.
segue abaixo o codigo do ultimo procedimento, linha 7:
procedure UpDateImovel;
begin
try
a ibq_rcimovel.Open;
b ibq_rcimovel.First;
c while not ibq_rcimovel.Eof do begin
d ibq_rscancel.SQL.Clear;
e ibq_rscancel.SQL.Add('update IMOVEL set imo_foientregue = ''N'' ');
f ibq_rscancel.SQL.Add('where imo_codigo = :imovel');
g ibq_rscancel.ParamByName('imovel').AsInteger := ibq_rcimovel.FieldByName('imo_codigo').AsInteger;
h ibq_rscancel.ExecSQL;
i ibq_rcimovel.Next;
j end;
k except
L raise;
m end;
n end;
Bem, o motivo da linha a é por causa do que acontece entre as linhas 1 e 3.
Quando eu provoco uma falha dentro da query, por exemplo: no lugar de imo_foientregue eu colocar imo_foient,
apresentará um erro a ser tratado na exceção externa, linha L. Acionando dessa forma o Rollback.
O problema é que ele esta gravando as duas procedures anteriores (UpDateContrato e UpDateCONXIMO), quando, na verdade era para dar um Rollback em tudo, não gravar nada.
Pois, minha intenção é essa, dando algum erro, não gravar nada.
Por valor alguém pode me ajudar? O que estou fazendo de errado?
Agradeço qualquer ajuda.

Vagner Almeida
Curtir tópico
+ 0Posts
28/06/2011
Teí Sistemas
Creio que o problema está após o except, onde você tenta levantar uma exceção usando apenas Raise. Isso apenas acaba não levantando a exceção. O comando correto é:
raise Exception.Create('Erro');
Onde você cria uma exceção e passa como parâmetro uma mensagem de erro, caso você queira que apareça.
Espero ter ajudado.
Gostei + 0
29/06/2011
Emerson Nascimento
Gostei + 0
29/06/2011
Junior Viesa
Gostei + 0
29/06/2011
Marco Salles
O queo Luciano disse anteriromente sobre propagar a exceção também a meu ver esta correto e se aplica mais ao seu caso
O que vc esta fazendo é ... Imagine
Try
bloco1
bloco2
bloco3
comita
excpet
ROOBACK
Sua idéia se algo der errado no Bloco1 / bloco2 / bloco3 ele caia no Roolback
Porém este Blocos também estão protegidos e a exceção levantada por eles estão sendo tratadas dentro deles o que faz
a excecução do programa seguir adiante
Por exemplo se dentro do bloco1 ocorrer uma exceção (como ela esta sendo tratada) a próxima limnha a ser executada será
a instruções do Bloco2 ... Agora se vc der um Raise exception.cretae dentro do Bloco voce estara EXTERNANDO a sua exceção e ela será lançada para fora , e ai sim , o Roolback será Executado
Acho que é isto
Gostei + 0
29/06/2011
Teí Sistemas
Exemplo:
1 2 3 4 5 6 7 8 9 10 | var bExecutou:Boolean Begin bExecutou := Funçao1; if bExecutou then bExecutou := Funcao2; if bExecutou then bExecutou := Funcao3; if bExecutou then Commit else Rollback; end; |
Gostei + 0
29/06/2011
Emerson Nascimento
O queo Luciano disse anteriromente sobre propagar a exceção também a meu ver esta correto e se aplica mais ao seu caso
O que vc esta fazendo é ... Imagine
Try
bloco1
bloco2
bloco3
comita
excpet
ROOBACK
Sua idéia se algo der errado no Bloco1 / bloco2 / bloco3 ele caia no Roolback
Porém este Blocos também estão protegidos e a exceção levantada por eles estão sendo tratadas dentro deles o que faz
a excecução do programa seguir adiante
Por exemplo se dentro do bloco1 ocorrer uma exceção (como ela esta sendo tratada) a próxima limnha a ser executada será
a instruções do Bloco2 ... Agora se vc der um Raise exception.cretae dentro do Bloco voce estara EXTERNANDO a sua exceção e ela será lançada para fora , e ai sim , o Roolback será Executado
Acho que é isto
Não Marco, você está equivocado.
teste o seguinte:
try
strtoint('A');
except
raise;
end
você verá que mesmo havendo o except, o comando raise levanta a exceção.
agora iniba a linha do raise e execute novamente. você verá que o sistema não acusa qualquer problema.
então o código do nosso amigo está correto. o problema é, sim, o ReconcileError.
aí alguém pode perguntar: e porque então fazer um except que levanta a exceção?
respondo: isso é útil se você quiser executar alguma rotina/comando após um erro e ainda assim exibir a exceção original. por isso existe essa montagem do try..except.
algo assim:
try
strtoint('A');
except
// executa suas rotinas de 'estorno'
[...]
// fim das rotinas de estorno
raise; // exibe a exceção original
end
Gostei + 0
30/06/2011
Marco Salles
È verdade .. Eu não uso assim , porque vc não consegue escrever deste modo numa Unidade . O Compilador do Delphi certamente irá reclamar
Muitas das veses é útil propagar uma exceção, até mesmo para tratar de forma correta qual a exceção de qual rotina gerou o erro . Mas ai se usa o Raise com a classe de erro especifica e não simplesmente o Raise
//uma classe especifica de exceção
type
TClasse_De_Erro_TAl = class (Exception);
try
codigo
except
Raise TClasse_De_Erro_TAl.Create('Mensagem que sera capturada'); //propagando o erro desta classe
end;
No retorno se pode testar para saber qual rotina que obteve o erro
except
on e: TClasse_De_Erro_TAl do
showmessage('ue Ocorreu o erro na rotina _Erro_TAl ');
.....
on e:excpetion do
showmessage('Erro mais genérico');
Esta é o modo usual . Mas Caso se queira saber o e exibir a exceção original . eu particularmente sempre utilizei assim
try
codigo
except
raise e.ClassType.Create; // lento a exceção com a classe original do erro para ser propagado fora do bloco
end;
e não utilizando um RAISE ..
try
codigo
except
raise ; //////////////isto em uma unidade o compilador irá reclamar
end;
Gostei + 0
09/05/2013
José
Gostei + 0