Fórum Problemas com Commit e RollBack #403951

28/06/2011

0

Olá!

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

Vagner Almeida

Responder

Posts

28/06/2011

Teí Sistemas

Olá Vagner,

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.

Responder

Gostei + 0

29/06/2011

Emerson Nascimento

o ClientDataset, por si só, não levanta exceção. você precisa fazer o tratamento no OnReconcileError do ClientDataset. force ali a geração da exceção.


Responder

Gostei + 0

29/06/2011

Junior Viesa

Eu usaria as procedures Updates como funções retornando um valor boolean e verificando o retornod e cada, se uma delas der false dou um rolback..
Responder

Gostei + 0

29/06/2011

Marco Salles

Amigo o que  emerson disse esta correto , mas não sei se aplica ao seu caso.

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
Responder

Gostei + 0

29/06/2011

Teí Sistemas

Uma outra maneira de escrever isto é usar funções, que, caso ocorra erro em alguma delas, ela retorne false, e assim não executasse as outras, dando um rollback. Mais ou menos como abaixo:

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;

Responder

Gostei + 0

29/06/2011

Emerson Nascimento

Amigo o que  emerson disse esta correto , mas não sei se aplica ao seu caso.

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

Ler Mais...



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



 
Responder

Gostei + 0

30/06/2011

Marco Salles

[qoute]Não Marco, você está equivocado.


È verdade .. Eu não uso assim , porque vc não consegue escrever deste modo numa Unidade  . O Compilador do Delphi certamente irá reclamar


aí alguém pode perguntar: e porque então fazer um except que levanta a exceção?


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;




Responder

Gostei + 0

09/05/2013

José

Este tópico esta sendo fechado por inatividade. Se necessário, sinalizar para que seja reaberto ou abrir um novo.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar