Array
(
)

while not ( executa milhões de vezes) até travar

Chip_set
   - 29 dez 2005

Ola pessoal, eu estava tentando fazer um loop como eu ja havia visto por aqui, mas encontrei um problema. Ele não para ... simplesmente executa tantas vezes que o sistema trava, tipo assim 250 vezes. O que será que fiz de errado, só mais um detalhe ele chegou a funcionar algumas vezes depois começou com isso. o código é esse ai.

procedure TForm_movimentos_cx.SpeedButton2Click(Sender: TObject);
var id_produto:integer; quantidade:double;
begin
if bancos.IBT_vendasSITUACAO.Value=´Em Aberto´ then
begin
bancos.IBT_itens_venda.First;
while not bancos.IBT_itens_venda.Eof do
begin
id_produto:=bancos.IBT_itens_vendaID_PRODUTOS.Value;
bancos.IBT_produtos.Locate(´COD_PRODUTO´, id_produto, []);
quantidade:=bancos.IBT_itens_vendaQUANTIDADE.Value;
bancos.IBT_produtos.Edit;
bancos.IBT_produtosSALDO.Value:=bancos.IBT_produtosSALDO.Value - quantidade;
bancos.IBT_produtos.Post;
bancos.IBT_produtos.ApplyUpdates;
bancos.IBT_produtos.Refresh;
bancos.IBT_produtos.Transaction.CommitRetaining;
gera_cod_movimento;
bancos.IBT_movimento_item.Insert;
bancos.IBT_movimento_itemCODIGO.Value:=cod_mov_novo;
bancos.IBT_movimento_itemDOCUMENTO.Value:=´Vendas´;
bancos.IBT_movimento_itemID_ITEM.Value:=bancos.IBT_produtosCOD_PRODUTO.Value;
bancos.IBT_movimento_itemTIPODEMOVIMENTO.Value:=´S´;
bancos.IBT_movimento_itemDATA_MOVIMENTO.Value:=date;
bancos.IBT_movimento_itemQUANTIDADE.Value:=quantidade;
bancos.IBT_movimento_itemVALOR.Value:=bancos.IBT_itens_vendaVALOR_UNIT.Value;
bancos.IBT_movimento_itemDOC_NUMERO.Value:=bancos.IBT_itens_vendaID_VENDAS.AsString;
bancos.IBT_movimento_item.Post;
gera_cod_mov_cx;
bancos.IBT_mov_cx_ent.Insert;
bancos.IBT_mov_cx_entCODIGO.Value:=cod_cx_novo;
bancos.IBT_mov_cx_entID_CAIXA.Value:=bancos.IBT_caixaCODIGO.Value;
bancos.IBT_mov_cx_entDATA_MOVIMENTO.Value:=date;
bancos.IBT_mov_cx_entFORMA_PAGAMENTO.Value:=bancos.IBT_vendasFOR_PAGAMENTO.Value;
bancos.IBT_mov_cx_entHISTORICO.Value:=´Venda´+´ - ´+ bancos.IBT_vendasOPERACAO.Value;
bancos.IBT_mov_cx_entNUM_DOC.Value:=bancos.IBT_vendasCODIGO.AsString;
bancos.IBT_mov_cx_entVALOR_REAL.Value:=bancos.IBT_vendasSUBTOTAL.Value;
bancos.IBT_mov_cx_entDESCONTO.Value:=bancos.IBT_vendasVALOR_DESCONTO.Value;
bancos.IBT_mov_cx_entVALOR_GERAL.Value:=bancos.IBT_vendasVALOR_TOTAL.Value;
bancos.IBT_mov_cx_ent.Post;
bancos.IBT_mov_cx_ent.ApplyUpdates;
bancos.IBT_mov_cx_ent.Refresh;
bancos.IBT_mov_cx_ent.Transaction.CommitRetaining;
calcula;
bancos.IBT_vendas.Edit;
bancos.IBT_vendasSITUACAO.Value:=´Baixado´;
bancos.IBT_vendas.Post;
bancos.IBT_vendas.ApplyUpdates;
bancos.IBT_vendas.Refresh;
bancos.IBT_vendas.Transaction.CommitRetaining;
bancos.IBT_itens_venda.Next;
end;
end else
begin
showmessage(´O Boleto ja está fechado´);
end;
end;

Gostaria de uma ajudinha ( de novo) rsrs.


Emerson
   - 29 dez 2005

#Código

procedure TForm_movimentos_cx.SpeedButton2Click(Sender: TObject);
var
id_produto:integer; quantidade:double;
begin
if bancos.IBT_vendasSITUACAO.Value=´Em Aberto´ then
begin
bancos.IBT_itens_venda.First;
while not bancos.IBT_itens_venda.Eof do
begin
id_produto:=bancos.IBT_itens_vendaID_PRODUTOS.Value;
bancos.IBT_produtos.Locate(´COD_PRODUTO´, id_produto, []);
quantidade:=bancos.IBT_itens_vendaQUANTIDADE.Value;
bancos.IBT_produtos.Edit;
bancos.IBT_produtosSALDO.Value:=bancos.IBT_produtosSALDO.Value - quantidade;
bancos.IBT_produtos.Post;
bancos.IBT_produtos.ApplyUpdates;
bancos.IBT_produtos.Refresh;
bancos.IBT_produtos.Transaction.CommitRetaining;
gera_cod_movimento;
bancos.IBT_movimento_item.Insert;
bancos.IBT_movimento_itemCODIGO.Value:=cod_mov_novo;
bancos.IBT_movimento_itemDOCUMENTO.Value:=´Vendas´;
bancos.IBT_movimento_itemID_ITEM.Value:=bancos.IBT_produtosCOD_PRODUTO.Value;
bancos.IBT_movimento_itemTIPODEMOVIMENTO.Value:=´S´;
bancos.IBT_movimento_itemDATA_MOVIMENTO.Value:=date;
bancos.IBT_movimento_itemQUANTIDADE.Value:=quantidade;
bancos.IBT_movimento_itemVALOR.Value:=bancos.IBT_itens_vendaVALOR_UNIT.Value;
bancos.IBT_movimento_itemDOC_NUMERO.Value:=bancos.IBT_itens_vendaID_VENDAS.AsString;
bancos.IBT_movimento_item.Post;
gera_cod_mov_cx;
bancos.IBT_mov_cx_ent.Insert;
bancos.IBT_mov_cx_entCODIGO.Value:=cod_cx_novo;
bancos.IBT_mov_cx_entID_CAIXA.Value:=bancos.IBT_caixaCODIGO.Value;
bancos.IBT_mov_cx_entDATA_MOVIMENTO.Value:=date;
bancos.IBT_mov_cx_entFORMA_PAGAMENTO.Value:=bancos.IBT_vendasFOR_PAGAMENTO.Value;
bancos.IBT_mov_cx_entHISTORICO.Value:=´Venda´+´ - ´+ bancos.IBT_vendasOPERACAO.Value;
bancos.IBT_mov_cx_entNUM_DOC.Value:=bancos.IBT_vendasCODIGO.AsString;
bancos.IBT_mov_cx_entVALOR_REAL.Value:=bancos.IBT_vendasSUBTOTAL.Value;
bancos.IBT_mov_cx_entDESCONTO.Value:=bancos.IBT_vendasVALOR_DESCONTO.Value;
bancos.IBT_mov_cx_entVALOR_GERAL.Value:=bancos.IBT_vendasVALOR_TOTAL.Value;
bancos.IBT_mov_cx_ent.Post;
bancos.IBT_mov_cx_ent.ApplyUpdates;
bancos.IBT_mov_cx_ent.Refresh;
bancos.IBT_mov_cx_ent.Transaction.CommitRetaining;
calcula;
bancos.IBT_vendas.Edit;
bancos.IBT_vendasSITUACAO.Value:=´Baixado´;
bancos.IBT_vendas.Post;
bancos.IBT_vendas.ApplyUpdates;
bancos.IBT_vendas.Refresh;
bancos.IBT_vendas.Transaction.CommitRetaining;

bancos.IBT_itens_venda.Next;
end;
end
else
showmessage(´O Boleto ja está fechado´);
end;


aparentemente está tudo certo.
verifique se as rotinas:
gera_cod_movimento;
gera_cod_mov_cx;
calcula;

não reposicionam o ponteiro de registros da tabela bancos.IBT_itens_venda


Chip_set
   - 29 dez 2005

olha só eu retirei o final do código e tudo rodou, agora fiquei sem entender.

bancos.IBT_vendas.Edit;
bancos.IBT_vendasSITUACAO.Value:=´Baixado´;
bancos.IBT_vendas.Post;
bancos.IBT_vendas.ApplyUpdates;
bancos.IBT_vendas.Refresh;
bancos.IBT_vendas.Transaction.CommitRetaining;


Michael
   - 29 dez 2005

Observando seu código, notei que vc chama ApplyUpdates e ´comita´ a transação a cada iteração do loop. A não ser por uma razão bem específica, isto quebra a atomicidade do processo. Se algum erro acontecer dentro do loop, as alterações já terão sido feitas no banco e vc não poderá desfazê-las com Rollback, e isso irá deixará seu banco inconsistente. Isso vale mesmo se forem várias transações distintas.

Rotinas de baixa são um excelente exemplo da utilidade de transações: ou salva tudo, ou não salva nada.

Eu deixaria o ApplyUpdates fora do loop, junto com o Commit, e não CommitRetaining. Seu uso não é aconselhado pq deixa a transação aberta mais tempo do que deveria, e isso pode gerar deadlocks dos registros sendo processados.

Outra coisa: Refresh refaz a consulta, e posiciona o cursor no início do DataSet. Como parece que Itens_vendas é uma tabela detalhe de Vendas, pode ser isso a causa do loop infinito. Cada vez que vc atualiza Vendas, o cursor volta para o começo do DataSet e vc processa os mesmos registros de novo.

[]´s