Fórum Transação Firebird DBExpress #317652
29/03/2006
0
Seguinte, tenho que gravar informações em duas tabelas, e caso dê algum problema, não gravar em nenhuma.
Então faço o seguinte.
No ClientDataSet1 os registros já estão inseridos e ´Post´.
Então:
InicioTransacao. try ClientDataSet1.ApplyUpdates(-1); ClientDataSet2.Insert; PreencheClientDataSet2; ClientDataSet2.Post; ClientDataSet2.ApplyUpdates(-1); Commit; except RoolBack; end;
problema é que os dados do primeiro client são gravados no banco, mesmo estando dentro da transação o apply;
Andremuller
Curtir tópico
+ 0Posts
29/03/2006
Vinicius2k
O método ApplyUpdates do TClientDataSet nunca gera exceção. Você precisa ´amarrar´ o Commit ou Rollback da transação ao número de erros ocorridos. Um exemplo:
{ ... }
var
TudoOK: Boolean;
Transacao: TTransactionDesc;
begin
try
{ **** Iniciando a transação **** }
Transacao.TransactionID:= 1;
Transacao.IsolationLevel:= xilReadCommitted;
SeuSQLConnection.StartTransaction(Transacao);
{ **** Aplicando os updates **** }
if ClientDataSet1.ApplyUpdates(0) = 0 then
begin
ClientDataSet2.Insert;
PreencheClientDataSet2;
ClientDataSet2.Post;
if ClientDataSet2.ApplyUpdates(0) = 0 then
TudoOK:= True;
// TudoOK só será true se não houver erro em nenhum Update
end;
{ **** Confirmando ou voltando a transação **** }
if TudoOK then
SeuSQLConnection.Commit(Transacao)
else
SeuSQLConnection.Rollback(Transacao);
except
// Ocorreu uma exceção qualquer no bloco ...
SeuSQLConnection.Rollback(Transacao);
end;
end;Outras dúvidas sobre transação com dbExpress podem ser esclarecidas usando a ferramenta de pesquisa do fórum.
Como exemplo, este tópico:
http://forum.clubedelphi.net/viewtopic.php?t=58547
Gostei + 0
04/05/2006
Rodolfo.pirolo
Digamos que estes dois clientdatsets referem-se a pedido e itens do pedido. Até aí beleza, só que preciso no momento da gravação destes dar baixa do meu estoque.
Tem como fazer utilizando esta mesma estrutura?
Atenciosamente,
Rodolfo
Gostei + 0
05/05/2006
Adriano Santos
Claro [b:1305852a2c]rodolfo.pirolo[/b:1305852a2c], como o [b:1305852a2c]Vinicius2K[/b:1305852a2c] disse:
No momento em que estiver gravando informações nos dois ClientDataSet´s você também pode elaborar uma rotina para gravar no Estoque, ou seja, dar o UpplyUpdates nas tabelas de estoque e testar se estes apply´s foram bem sucedidos, veja no exemplo do [b:1305852a2c]Vinicius2k[/b:1305852a2c] em outro tópico:
var TudoOK: Boolean; Transacao: TTransactionDesc; begin TudoOK:= False; Transacao.TransactionID:= 1; Transacao.IsolationLevel:= xilReadCommitted; SQLConnection1.StartTransaction(Transacao); // Aplicando os updates if ClientDataSet1.ApplyUpdates(0) = 0 then if ClientDataSet2.ApplyUpdates(0) = 0 then if ClientDataSet3.ApplyUpdates(0) = 0 then if ClientDataSet4.ApplyUpdates(0) = 0 then TudoOK:= True; // Note que TudoOK só será true se não houver nenhum erro em nenhum dos Updates if TudoOK then begin SQLConnection1.Commit(Transacao); ShowMessage(´Atualizações OK.´); end else begin SQLConnection1.Rollback(Transacao); ShowMessage(´Ocorreram erros. Alterações descartadas.´); end; end;
Aki o TudoOK só ficará True se todos os ApplyUpdates forem OK.
Tô certo [b:1305852a2c]Vinicius[/b:1305852a2c]???
Gostei + 0
05/05/2006
Rodolfo.pirolo
Desculpe-me, acho que não fui claro na minha questão.
Minha dúvida é a seguinte:
Gostaria de montar uma atualização desta maneira:
...
if ClientDataSet2.ApplyUpdates(0) = 0 then
Para cada item do meu CDS_Item_pedidos
update estoque set qtde_estoque = qtde_estoque - qtde_vendida
ApplyUpdates
Se tudo terminar bem, commit
senão rollback em tudo.
Isto é possivel? Ainda não sei como atualizar o estoque com applyupadates, porque para esta rotina estou usando Store Procedure. Talvez criar um cds para atualizá-lo.
Atenicosamente,
Rodolfo
Gostei + 0
05/05/2006
Renatacoimbra
usando o Exemplo do colega Vinicius2K, basta vc dar baixa no seu estoque e só gravar em memoria usando o Post.
depois vc usa o ApplyUpdate, e se o ApplyUpdate for bem sucedido vc comita.
[]´s
Gostei + 0
05/05/2006
Vinicius2k
Particularmente, eu prefiro manter a baixa de estoque como uma trigger ´After Insert´ na tabela de ítens. É mais prático do que Stored Procedure, na minha opinião.
Porém, se você não desejar ou não puder deixar esta regra do negócio no SGBD. Pode implementar algo parecido com isto:
var TudoOK: Boolean; Transacao: TTransactionDesc; I: Integer; begin TudoOK:= False; // Definindo instrução para o update do estoque SQLDataSet1.CommandText := ´update ESTOQUE set QTDE = QTDE - :venda where IDPRODUTO = :idproduto´; Transacao.TransactionID:= 1; Transacao.IsolationLevel:= xilReadCommitted; SQLConnection1.StartTransaction(Transacao); // Aplicando os updates if ClientDataSet1.ApplyUpdates(0) = 0 then begin if ClientDataSet2.ApplyUpdates(0) = 0 then begin try for I := 0 to ClientDataSet2.RecordCount - 1 do begin // Atualizando o estoque. SQLDataSet1.ParamByName(´venda´).AsInteger := ClientDataSet2.FieldByName(´qtde´).AsInteger; SQLDataSet1.ParamByName(´idproduto´).AsInteger := ClientDataSet2.FieldByName(´idproduto´).AsInteger; SQLDataSet1.ExecSQL; end; TudoOK := True; except // Erro ao atualizar o estoque TudoOK := False; end; end; end; // Note que TudoOK só será true se não houver nenhum erro em nenhum dos Updates if TudoOK then begin SQLConnection1.Commit(Transacao); ShowMessage(´Atualizações OK.´); end else begin SQLConnection1.Rollback(Transacao); ShowMessage(´Ocorreram erros. Alterações descartadas.´); end; end;
Gostei + 0
05/05/2006
Rodolfo.pirolo
Corrija-me se estiver errado, quando mando executar a instrução sql de atualização do estoque conforme voce demonstrou, caso der um erro, quando executar o rollback, ele não retornará os valores anteriores.
Exemplo:
1° registro: atualizado com sucesso.
2° registro: atualizado com sucesso.
3° registro: erro na atualização.
Neste caso o rollback não alterará os valores do primeiro e segundo lançamentos.
Estou certo ou errado?
Abraços
Rodolfo
Gostei + 0
06/05/2006
Vinicius2k
Tudo o que você faz envolto na mesma transação é afetado pelo commit ou rollback.
Você poderia ter centenas de updates que, se eles estiverem todos dentro da mesma transação (que é o nosso caso), ao ser dado o rollback, tudo seria desfeito, incluindo triggers e SPs executadas pelo SGBD.
Fique tranquilo quanto a isso. ;)
Gostei + 0
10/05/2006
Rodolfo.pirolo
Obrigado, funcionou belezinha.
Só desculpe-me pela demora da resposta, somente hoje pude testar a sua idéia.
Obrigado também ao Adriano Santos e a Renata Coimbra.
Abraços,
Rodolfo
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)