Controlando erros em uma venda para evitar inconsistências
31/08/2004
0
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
Posts
31/08/2004
Macario
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.
31/08/2004
Xtreme
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;
31/08/2004
Xtreme
Obs.: o transaction é um componente ex.: IBTransaction (na paleta do interbase).
31/08/2004
Vinicius2k
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+
31/08/2004
Xtreme
31/08/2004
Vinicius2k
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+
Clique aqui para fazer login e interagir na Comunidade :)