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

29/12/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.


Chip_set

Respostas

29/12/2005

Emerson

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, [&93;);
      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:
[i:34cf79d6bf]gera_cod_movimento;
gera_cod_mov_cx;
calcula;[/i:34cf79d6bf]
não reposicionam o ponteiro de registros da tabela [b:34cf79d6bf]bancos.IBT_itens_venda[/b:34cf79d6bf]


Responder Citar

29/12/2005

Chip_set

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;


Responder Citar

29/12/2005

Michael

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: [b:c36731db65]Refresh [/b:c36731db65]refaz a consulta, e posiciona o cursor no início do DataSet. Como parece que [b:c36731db65]Itens_vendas[/b:c36731db65] é uma tabela detalhe de [b:c36731db65]Vendas[/b:c36731db65], 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


Responder Citar