Gravar Itens de uma Solicitação
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, é:
Código do botão IncluirSolicitacao (aqui eu precisarei de uma ajuda) que escrevi é:
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
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
Curtidas 0
Respostas
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:
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
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
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...
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
05/03/2006
Ah, esqueci de mudar de TDU para TDI em duas partes... então, é TDI...
GOSTEI 0
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:
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:
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
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
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.
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
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,
Valeu pela informação.
Abraço,
GOSTEI 0
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
05/03/2006
Ok, suas explicações me ajudaram muito, valeu...
GOSTEI 0