Controlando erros em uma venda para evitar inconsistências

31/08/2004

Trabalho com Firebird 1.5 e utilizo o DBExpress para relacionamentos com o banco de dados.
Quando eu gravo uma venda, faço alterações em várias tabelas (na própria venda, no produtos, ctas receber, etc).
Os últimos comandos da rotina de gravação da venda são assim:

try
EstoqueProdutos. ApplyUpdates(0);
ContasReceber.ApplyUpdates(0);
VendaMestre.ApplyUpdates(0);
except
ShowMessage(´ocorreu um erro´);

Até aqui tudo certo. Agora vem minha dúvida/problema: na rotina acima, dentro do try, há três comandos. Se o primeiro comando (EstoqueProdutos.Appp...) der erro, nada é gravado. Mas e se por exemplo, ocorrer um erro no no último comando dentro do try (VendaMestre.app...), as outras duas tabelas teriam sido alteradas indevidamente, pois a venda não foi gravada devido ao erro.
Pergunto: como controlar isso? Como ficaria uma rotina correta para isso?

Obrigado


Valdirdill

Respostas

31/08/2004

Macario

olá colega bom dia.

Bom não manjo muito de SQL, mas procure no forum topicos sobre Transações. Toda essa rotina de gerar a nota deve ficar dentro de uma transação, assim se em algum ponto houver falha será aplicado um rollback em tudo.

E aguarde mais explicações dos nossoa colegas.


Responder Citar

31/08/2004

Xtreme

try
EstoqueProdutos. ApplyUpdates(0);
ContasReceber.ApplyUpdates(0);
VendaMestre.ApplyUpdates(0);
except
ShowMessage(´ocorreu um erro´);
[b:66d371307e]transaction.rollback;[/b:66d371307e]//desta forma vc digamos assim cancela toda e qualquer alteracao feita no banoc de dados
end;


Responder Citar

31/08/2004

Xtreme

try EstoqueProdutos. ApplyUpdates(0); ContasReceber.ApplyUpdates(0); VendaMestre.ApplyUpdates(0); except ShowMessage(´ocorreu um erro´); [b:19e8454e66]transaction.rollback;[/b:19e8454e66]//desta forma vc digamos assim cancela toda e qualquer alteracao feita no banco de dados end;


Obs.: o transaction é um componente ex.: IBTransaction (na paleta do interbase).


Responder Citar

31/08/2004

Vinicius2k

Colega,

Existem 2 problemas :
1. Se não houver controle explícito de transação muita coisa pode dar errado. O que for aplicado sem erros não é desfeito, pois está existindo uma transação diferente para cada ApplyUpdates...
2. O método ApplyUpdates NUNCA gera exceção para erros vindos do banco de dados... então try/except não resolve.

O que vc precisa fazer é controlar a transação e verificar sempre o valor de retorno do método ApplyUpdates (ele retorna o número de erros ocorridos na tentativa de aplicação)...
Um exemplo seria :
var 
  TudoOK: Boolean;
  TD: TransactionDesc; 
try 
  TudoOK:= False;    
  TD.TransactionID:= 1; 
  TD.IsolationLevel:= xilReadCommitted; 
  SQLConnection1.StartTransaction(TD); 
  {****} 
  if EstoqueProdutos.ApplyUpdates(0) = 0 then 
    if ContasReceber.ApplyUpdates(0) = 0 then
      if VendaMestre.ApplyUpdates(0) = 0 then 
        TudoOK:= True; 
  {****}  
  if TudoOK then SQLConnection1.Commit(TD) 
    else 
      begin 
        ShowMessage(´Ocorreram erros !´); 
        SQLConnection1.Rollback(TD);        
      end; 
except 
  On E: Exception do 
    ShowMessage(´Não foi possível abrir a transação.´ + #13 + E.Message); 
end;


Vc pode fazer uma pesquisa aqui no fórum sobre Transação + dbExpress q vc terá outros exemplos... veja tbm este tópico recente: http://delphiforum.icft.com.br/forum/viewtopic.php?t=50822

Espero ter ajudado...
T+


Responder Citar

31/08/2004

Xtreme

Uma pequena duvida Vinicius2k, da forma que esta seu exemplo no momneto do commit/rollback todas as transacoes serao fechadas ou somente aquelas com a qual vc esta fazendo no seu exemplo?


Responder Citar

31/08/2004

Vinicius2k

Somente ela...
Commit(TD) : o record ´TD´ tem a ´TransactionID´ que identifica a transação que vc quer dar start, commit ou rollback, mas isto só vale para dbExpress pq a SQLConnection suporta várias transações simultâneas...

Se vc estiver usando IBX e quiser trabalhar com múltiplas transações simultâneas, precisa de múltiplos IBTransactions... OK?

T+


Responder Citar

31/08/2004

Xtreme

Beleza vinicius2k valew pela explicação cara! Falow.


Responder Citar