Controlando erros em uma venda para evitar inconsistências
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
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
Curtidas 0
Respostas
Macario
31/08/2004
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.
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.
GOSTEI 0
Xtreme
31/08/2004
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;
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;
GOSTEI 0
Xtreme
31/08/2004
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).
GOSTEI 0
Vinicius2k
31/08/2004
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 :
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+
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+
GOSTEI 0
Xtreme
31/08/2004
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?
GOSTEI 0
Vinicius2k
31/08/2004
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+
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+
GOSTEI 0
Xtreme
31/08/2004
Beleza vinicius2k valew pela explicação cara! Falow.
GOSTEI 0