Gravar Itens de uma Solicitação

Firebird

05/03/2006

Olá amigos!!!!

Essa é a primeira vez que estou fazendo este processo. Tenho duas tabelas:

TABELA SOLICITACAO - COD_SOLIC, OPERADOR *, DATA, HORA, UNIDADE

TABELA ITENS - COD_ITEM, COD_SOLIC, CARTUCHO *, MARCA, QTDE

* Não usei código nestas duas situações, pois estou fazendo de uma maneira simples, pois o que me importa neste momento é como fazer o processo.

Este sistema trata-se de um controle de cartuchos, onde é feito um pedido de cartuchos para ser disponibilizado a uma determinada filial.

No botão gravar pedido, não é gerado erros, tanto que o registro é gravaado na tabela de SOLICITACAO, porém estou tendo dificuldades quando tento incluir um item na tabela ITENS.

O código que utilizei no botão GRAVAR SOLICITAÇÃO, que aparentemente está correto, é:

procedure TfrmSolicitacao.btnGravarSolicitacaoClick(Sender: TObject);
var
  TDS : TTransactionDesc;
begin
  try
    TDS.TransactionID := 1;
    TDS.IsolationLevel := xilREADCOMMITTED;

    with dm.cdsInserirPedido do
    begin

      dm.sqlConexao.StartTransaction(TDS);
      FieldByName(´OPERADOR´).AsString := edtOperador.Text;
      FieldByName(´DATA´).AsDateTime := dtpData.Date;
      FieldByName(´HORA´).AsDateTime := strtotime(mskedtHora.Text);
      FieldByName(´UNIDADE´).AsString := edtUnidade.Text;

      dm.sqlConexao.Commit(TDS);
      ApplyUpdates(0);
      Refresh;
      Last;
      edtSolicitacao.Text := inttostr(FieldByName(´COD_SOLIC´).AsInteger);

    end;
  except
    on E : Exception do
    begin
      dm.sqlConexao.Rollback(TDS);
      showmessage(E.Message);
    end;
  end;
  
  // Atualizar o codigo da solicitação na tabela ITENS
  with dm.cdsAtualizaCodSolic do
  begin
    close;
    Params.ParamByName(´CODSOLIC´).AsInteger := strtoint(edtSolicitacao.Text);
    execute;
  end;

  btnGravarSolicitacao.Enabled := false;
  btnNovaSolicitacao.Enabled := true;
end;


Código do botão IncluirSolicitacao (aqui eu precisarei de uma ajuda) que escrevi é:

procedure TfrmSolicitacao.btnIncluirItemClick(Sender: TObject);
var
  TDI : TTransactionDesc;
begin
  try
    TDI.TransactionID := 1;
    TDI.IsolationLevel := xilREADCOMMITTED;

    with dm.cdsIncluirItem do
    begin
      dm.sqlConexao.StartTransaction(TDI);

      FieldByName(´COD_SOLIC´).AsInteger := 0;
      FieldByName(´ITEM´).AsString := edtItem.Text;
      FieldByName(´MARCA´).AsString := edtMarca.Text;
      FieldByName(´QTDE´).AsInteger := strtoint(edtQtde.Text);

      dm.sqlConexao.Commit(TDI);
      ApplyUpdates(0);
      Refresh;
      Last;
    end;
  except
    on E : Exception do
    begin
      dm.sqlConexao.Rollback(TDI);
      showmessage(E.Message);
    end;
  end;

  btnIncluirItem.Enabled := false;
  btnNovoItem.Enabled := true;
  
end;


Quando clico no botão Incluir Item, aparece a mensagem - traduzida - ´não há nenhuma transação ativa´


Essa é uma típica situação que ocorre, por exemplo, numa venda de produtos, onde é feito um pedido de uma determinada quantidade de itens. Pesquisei, mas não encontrei a solução desejada. Gostaria que me apontassem o erro, e qual seria a melhor solução.

Fico no aguardo.

Um abraço a todos....

Rogério


Roger1976

Roger1976

Curtidas 0

Respostas

Vinicius2k

Vinicius2k

05/03/2006

Colega,

Verifique a ordem em que você efetua as operações.
Como você está utilizando TClientDataSet ela deve ser:
- Insere, Altera, Exclui dados no CDS.
- Abre transação.
- Aplica os updates.
- Fecha transação.

Você está abrindo e fechando a transação antes de aplicar os updates e isto está ´meio estranho...´ Outro detalhe é que try...except com ClientDataSets não tem nenhum efeito pois ele nunca gera exceção.

Ex:
procedure TfrmSolicitacao.btnGravarSolicitacaoClick(Sender: TObject);
var
  TDS : TTransactionDesc;
begin
  TDS.TransactionID := 1;
  TDS.IsolationLevel := xilREADCOMMITTED;
  with dm.cdsInserirPedido do
  begin

    FieldByName(´OPERADOR´).AsString := edtOperador.Text;
    FieldByName(´DATA´).AsDateTime := dtpData.Date;
    FieldByName(´HORA´).AsDateTime := strtotime(mskedtHora.Text);
    FieldByName(´UNIDADE´).AsString := edtUnidade.Text;

    dm.sqlConexao.StartTransaction(TDS);
    if ApplyUpdates(0) = 0 then
      dm.sqlConexao.Commit(TDS);
    else
    begin
      dm.sqlConexao.Rollback(TDS);
      ShowMessage(´Ocorreram errros ao aplicar as atualizações.´);
    end;
    Refresh;
    Last;
    edtSolicitacao.Text := inttostr(FieldByName(´COD_SOLIC´).AsInteger);
    end;
  end;
  
  // Atualizar o codigo da solicitação na tabela ITENS
  with dm.cdsAtualizaCodSolic do
  begin
    close;
    Params.ParamByName(´CODSOLIC´).AsInteger := strtoint(edtSolicitacao.Text);
    execute;
  end;

  btnGravarSolicitacao.Enabled := false;
  btnNovaSolicitacao.Enabled := true;
end;


procedure TfrmSolicitacao.btnIncluirItemClick(Sender: TObject);
var
  TDI : TTransactionDesc;
begin
  TDI.TransactionID := 1;
  TDI.IsolationLevel := xilREADCOMMITTED;

  with dm.cdsIncluirItem do
  begin

    FieldByName(´COD_SOLIC´).AsInteger := 0;
    FieldByName(´ITEM´).AsString := edtItem.Text;
    FieldByName(´MARCA´).AsString := edtMarca.Text;
    FieldByName(´QTDE´).AsInteger := strtoint(edtQtde.Text);

    dm.sqlConexao.StartTransaction(TDI);
    if ApplyUpdates(0) = 0 then
      dm.sqlConexao.Commit(TDS);
    else
    begin
      dm.sqlConexao.Rollback(TDI);
      ShowMessage(´Ocorreram errros ao aplicar as atualizações.´);
    end;
    dm.sqlConexao.Commit(TDI);
    Refresh;
    Last;
  end;

  btnIncluirItem.Enabled := false;
  btnNovoItem.Enabled := true;
  
end;


Faça as mudanças no seu código e observe os resultados. Se tiver dúvidas sobre transações e dbExpress, consulte este típico:
http://forum.clubedelphi.net/viewtopic.php?t=58547


GOSTEI 0
Roger1976

Roger1976

05/03/2006

Kra, eu fiz algumas alteraçoes no código, e agora está funcionando. Dei um insert primeiro na tabela de SOLICITACAO (estava dando depois), peguei o codigo gerado e passei para o codigo da solicitação da tabela de ITENS.

procedure TfrmCadUser.btnIncluirItemClick(Sender: TObject);
var
TDI : TTransactionDesc;
begin
try
TDU.TransactionID := 1;
TDU.IsolationLevel := xilREADCOMMITTED;

//dm.sqlConexao.StartTransaction(TDI);

with dm.cdsIncluirItem do
begin
FetchParams;
dm.sqlConexao.StartTransaction(TDI);

Params.ParamByName(´COD_SOLIC´).AsInteger := strtoint(edtSolicitacao.Text);
Params.ParamByName(´ITEM´).AsString := edtItem.Text;
Params.ParamByName(´MARCA´).AsString := edtMarca.Text;
Params.ParamByName(´QTDE´).AsInteger := strtoint(edtQtde.Text);

execute;
dm.sqlConexao.Commit(TDI);

// mostrar o item gravado na dbgid toda vez que um novo for inserido
with dm.cdsCodSolic do
begin
close;
Params.ParamByName(´CODSOLICIT´).AsInteger := strtoint(edtSolicitacao.Text);
open;

if not isempty then
begin
dbgrid1.DataSource := dm.dsCodSolic;
last;
end;
end;

end;
except
on E : Exception do
begin
dm.sqlConexao.Rollback(TDI);
showmessage(E.Message);
end;
end;

end;

Como vc pode perceber neste código, eu fiz muitas mudanças, que proporcinaram enfim o resultado desejado.

Muito obrigado pela dica do clientdataset, pois como sou novato, não sabia que estando em try/except não gera exeção, então vc remenda q eu faça se o uso dele?

Caso tenha alguma sugestão a fazer neste trecho, ficarei grato.

Valeu Vinícius...


GOSTEI 0
Roger1976

Roger1976

05/03/2006

Ah, esqueci de mudar de TDU para TDI em duas partes... então, é TDI...


GOSTEI 0
Vinicius2k

Vinicius2k

05/03/2006

Com certeza eu recomendo o uso de TClientDataSet, pois a Midas facilita bastante o processo de acesso e manipulação de dados deixando a aplicação bastante flexível.

O seu try...except só vai capturar erros do TSQLConnection e outros e do próprio CDS em todos seus métodos, menos no ApplyUpdates.

Ele não gerar exceção, não quer dizer que você não possa capturar seus erros. O método ApplyUpdates retorna o número de erros ocorridos durante a tentativa de aplicação das atualizações.
Então, em um teste simples você consegue saber se houve algum erro:
if CDS.ApplyUpdates(0) > 0 then 
  ShowMessage(´Erro!´);


Você ainda pode exibir ao usuário a mensagem de erro e tomar alguma providência, utilizando o evento [b:c766b1fbcc]OnReconcileError[/b:c766b1fbcc] do CDS. Um exemplo simples, escrito neste evento:
ShowMessage(E.Message);



GOSTEI 0
Roger1976

Roger1976

05/03/2006

Vinicios, a verificaçao do erro do CDS (if cds.applyupdates(0) > 0) deverá ser escrita em que parte do código?


GOSTEI 0
Vinicius2k

Vinicius2k

05/03/2006

Quando for necessário chamar o método ApplyUpdates. O que não é o caso do seu segundo código, aonde você não utiliza ApplyUpdates mas sim um inserção direta.
Se aplicaria apenas ao primeiro código e você poderia fazer como no exemplo que dei, ainda relacionado ao primeiro código.


GOSTEI 0
Roger1976

Roger1976

05/03/2006

Entendi Vinícius, uma dúvida final, a inserção direta (como fiz no segundo caso) é mais recomendada do que a utilização do método applyupdates? Será que no primeiro caso eu não estaria carregando todos os dados no clientdataset, e ao final da gravação, selecionando o último registro (o que foi gravado), o que não ocorre na inserção direta?

Valeu pela informação.

Abraço,


GOSTEI 0
Vinicius2k

Vinicius2k

05/03/2006

...a inserção direta (como fiz no segundo caso) é mais recomendada do que a utilização do método applyupdates?

Depende do caso... Existem situações aonde a inserção direta via SQL é mais recomendada por ser mais simples de utilizar e controlar. Em outros, como cadastros, por exemplo, é muito mais prático você utilizar os métodos do CDS.
Será que no primeiro caso eu não estaria carregando todos os dados no clientdataset, e ao final da gravação, selecionando o último registro (o que foi gravado), o que não ocorre na inserção direta?

Acho que não entendi... Se eu tiver entendido corretamente a sua dúvida, a resposta seria não. Você não estaria gravando efetivamente apenas o último registro. Todo o buffer do CDS é gerenciado pela Midas e ´ela sabe´ exatamente o que foi inserido, alterado ou deletado do buffer e serão todas estas modificações que serão enviadas ao SGBD pelo TDataSetProvider no momento que você chamar o ApplyUpdates do CDS.


GOSTEI 0
Roger1976

Roger1976

05/03/2006

Ok, suas explicações me ajudaram muito, valeu...


GOSTEI 0
POSTAR