Erro ao inserir em tb com campos identitiy no sql server 2008

18/02/2010

Pessoal isso mesmo, na hora de inserir um registro o clientdataset não esta mandando para o banco, no meu entender o campo identity e como um default ou como se existisse um trigger para disparalo, vejam a vídeo e retornem o mais rápido possível

[#VIDEO-179#]
Carlos Faria

Carlos Faria

Curtidas 0

Respostas

Carlos Faria

Carlos Faria

18/02/2010

Rodrigo um vez eu abri um chamado onde o banco nao tava querendo inserir lembra que voce ate fez uma transação para tentar forçar o registro a entrar no banco , acho que esse chamado e o mesmo daquele ,porem agora eu ja identifiquei que o problema pelo menos na versao 2008 do sql e o campo identity
GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Ola Rodrigo eu outra vez, Bom eu pesquisei aqui e encontrei uma solução que não me parece nada boa, daria uma trabalheira danada e perderia muito em produtividade. Fiz o seguinte teste criei duas tabelas diferentes Tb_teste1 e Tb_Teste2 com os mesmo parâmetros, para cada clientdataset eu adicionei um sqldataset e um datasetprovider ou seja , fiquei em um único datamodule com 2 sqldataset e 2 datasetprovider sendo que setando a propriedade poAllowCommandtext de um datasetprovider eu poderia adicionar quantos clientdataset quisesse. Sendo assim a meu ver se tiver outra maneira e não precisar fazer assim um trio para cada clientdataset (sqldataset, datasetprovider, clientdataset) eu agradeceria. Mas a palavra final ai e sua.
GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

e claro esqueci de falar o mais importante no sqldataset adicionei os fields e ai sim , informei que o campo id nao é requerido , ai deu tudo certo ! mas dessa maneira acho trabalhoso demais   se possivel uma video caprichada , ja faz tempo que tu nao faz uma rs
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Certo carlos, vou gravar e te envio,

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Ok Rodrigo Fico esperando mais uma vez , retifico usar um sqlconnetion + sqldataset + datasetprovider com a propriedade poAllowCommandtext para true é um maravilha isso , agente precisa de criar apenas um trio de componentes e vai adicionando clientdataset , porem quando o campo e identity so da certo se agente adicionar o tfields na sqldataset e dizer que o campo autoincremento não é requerido. Bom isso para mim não é bom pois teria que colocar centenas de componentes no projeto , centenas de sqldataset e datasetprovider . se tiver um jeito de driblar isso agradeço muito  
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Segue a Video:

http://video.devmedia.com.br/discovirtual/162135/Chamado_15827_Final.rar

Att,
GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

VOU ANALIZAR TUDO AQUI E TE RETORNO O MAIS RAPIDO POSSIVEL  
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Ok,

Estamos aguardando então.

Abs!!!

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Ola grande Rodrigo. Bom eu fiz alguns ajustes aqui, exatamente como você fez no seu sistema de vendas. Praticamente quase do mesmo jeito. Agora eu vou inserir na tabela Tb_vendas aquele resumo da venda, qt_items,Subtotal ,Id_Cliente e etc. , nessa tabela o campo será autoimcremento.Na tabela itens vendas ai sim vou inserir todos os itens daquela venda , porem eu preciso capturar o id_venda antes de inserir e não pode ser como você me mostrou no vídeo pois será uma grande quantidade de maquinas assecando o sistema. A pergunta é Como eu vou capturar o id_venda usando Delphi ,sqlserver e dbexpress ?   Eu poderia criar uma procudere de insert na Tb_vendas como um campo @retorno pegar o id_venda e trabalhar com ele na Tb_items_Venda , mas ficaria estranho , clientdataset , sqlproc e etc   Da uma luz meste   Não preciso que o usuário veja o numero Id_Venda na tabela , apenas que após inserir na Tb_vendas , eu pegue e id_venda , e jogue no clientdaset que vai inserir na Tb_intens venda É claro tudo isso ficara dentro de uma transação, se não se houver algum erro posso inserir na tabela Tb_vendas e não ter itens relacionados com aquela venda;
GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010


  cdsItemVenda.Open ;
  cdsItemVenda.First;
  while not cdsItemVenda.Active do
  begin
    cdsItemVenda.Append;
    cdsItemVendaid_venda.AsInteger := 29;  //colocar a variavel aqui
    cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
    cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
    cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
    cdsItemVendaId_Vendedor.AsInteger := 1;
    cdsItems.Next ;
    cdsItemVenda.Post;
    end ;
    cdsItemVenda.ApplyUpdates(0); tenho 2 clientdaset um de memoria e outro conectado , peguei o exemplo la no teu curso , so nao sei o que estou fazerndo de errado aqui , cdsitems e o clientdataset offline , cdsitemvenda o que finaliza , enato seja se o camarada encher o grid com 15 pedidos tenho que gravar os 15 registros , o que ta errado aqui  ????????? outra questao e a situação que te informei no texto anterior , por ser uma quantidade grande de maquinas acessando o sistema , nao pode haver erros e questao de capturar o id eu ja resolvi com um stored procedure id_venda int output select @@identity as @retorno , a proc insere , me traz o numero e inserio nos detalhes , mas to achando isso meio porcao afinal estou trabalhando com clientdataset , me diz vc o que achas ? aquele seu exemplo de como capturar o id_antes do insert no sql server eu nao consegui se vc tiver um exemplo mais claro ai agradeço outra coisa o exemplo que vc me demostrou com a query funciona sim ,testei aqui , mais poder haver error serissiomos se mais de um atendente acessar ao mesmo tempo , melhor tentarmos uma solucao meslhoe estive analizando a seguinte situação talves nesse caso a proc seja melhor , pois eu nao vou ter um id_venda na tela somente quando ela realmente for concluida , e posso fazer tudo isso dentro de uma transacao , cadastro a venda e itens da venda , assim se mais de um usuario acessar o sistema ao mesmo tempo nao tem erro , afinal o campo e do tipo identiy e so vou ter ele depois de inserido os registros ? vc que é o mestre ai , da uma ideia que eu faço aqui , Quanto a questao do Loop cara se puder ser hoje ainda urgente , passei a noite toda enrolado tentando fazer esse loop funcionar aqui rs
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Carlos Esta dando mole kk

O metodo e while not cdsItemVenda.EOF do  e não while not cdsItemVenda.Active do


Veja como ficaria:




cdsItemVenda.Open ;
  cdsItemVenda.First;
  while not cdsItemVenda.EOF do
  begin
    cdsItemVenda.Append;
    cdsItemVendaid_venda.AsInteger := 29;  //colocar a variavel aqui
    cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
    cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
    cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
    cdsItemVendaId_Vendedor.AsInteger := 1;
    cdsItems.Next ;
    cdsItemVenda.Post;
    end ;
    cdsItemVenda.ApplyUpdates(0);


Abs!!


GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

na verdade o metodo active eu escrevi pq escrevi rapido e sem revisar o que acontece é o seguinte cdsItemVenda.Open ;  //cdsligado ao banco
  cdsItemVenda.First;
  while not cdsItemVenda.EOF do
  begin
    cdsItemVenda.Append;
    cdsItemVendaid_venda.AsInteger := 29;  //colocar a variavel aqui
    cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
    cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
    cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
    cdsItemVendaId_Vendedor.AsInteger := 1;
    cdsItems.Next ; //cds de memoria
    cdsItemVenda.Post;
    end ;
    cdsItemVenda.ApplyUpdates(0);

Cdsitemvenda é co clientdaset que vai dar um insert nao tb_item_vendas esse cds e conectado a banco Cdsitems esse e de memoria , offline como vc diz , nao esta funcionando o lação , eu copiei e colei exatamente como vc mandou nao esta varrendo os dados inseridos na grid ??????????????? 
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Roda a aplicacao com F9 executa e tentar gravar.

Me manda a mensagem do erro ou se prefirir grave um video me mostrando como tudo esta conectado e como vc fez o codigo que fica mais facil.


Estou no aguardo !!


Attt,

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Aqui eu ja achei o erro , o que aconteceu foi que voce fez o mesmo erro que eu ,rs o clientdataset que precisa entrar no loop é o cdsitems (clientdataset) de memoria e nao o clientdataset do banco oberve nas linhas vermelhas que apos alterado tudo deu certo agora ,posso encher a grid que grava tudo,porem ainda ta dando um erro apenas eu coloque isso dentro de um bloco de transaction   procedure TfrmVendas.btnConfirmaClick(Sender: TObject);
var
  t: TDBXTransaction;
begin
  try
    t := DM.SQLConnection.DBXConnection.BeginTransaction(TDBXIsolations.ReadCommitted);
    pri_vendas;
    pri_item_venda;
    DM.SQLConnection.DBXConnection.CommitFreeAndNil(t);  except
     DM.SQLConnection.DBXConnection.RollbackFreeAndNil(t);
    //ShowMessage(Venda nao realizada ');
  end;
  end;   a procedure pri_items_Venda nada mais e que   cdsItemVenda.Open;
cdsItems.First;
 while not cdsItems.EOF do
begin
  cdsItemVenda.Append;
  cdsItemVendaid_venda.AsInteger := xVenda;
  cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;          cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0);     porem ao colocar um brack point ele entra nessa rotina do cliente dataset e fica em loop infinito e nao roda

codigo correto cdsItemVenda.Open;
cdsItems.First;
 while not cdsItems.EOF do
begin
  cdsItemVenda.Append;
  cdsItemVendaid_venda.AsInteger := xVenda;
  cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;          cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0);
seu codigo (alias nosso codigo melhor dizendo eu e vc caimos no mesmo erro rs)
cdsItemVenda.Open ;  //cdsligado ao banco
  cdsItemVenda.First;
  while not cdsItemVenda.EOF do
  begin
    cdsItemVenda.Append;
    cdsItemVendaid_venda.AsInteger := 29;  //colocar a variavel aqui
    cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
    cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
    cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
    cdsItemVendaId_Vendedor.AsInteger := 1;
    cdsItems.Next ; //cds de memoria
    cdsItemVenda.Post;
    end ;
    cdsItemVenda.ApplyUpdates(0);  
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

kkkkkkkkkkkkk

Putz que mole ein.  kkkk Realmente não reparei. Mas tai ja pegou o jeito da depuração.

Att,

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

mas o que vc me diz da transação , é necessaria afinal vou inserir em 2 tabelas diferentes ou faço isso tudo com clientdatset mesmo
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Olá Carlos,

Desculpe esqueci de mencionar isso.

Não precisa de transação o clientDataSet ja faz transsação interno por isso que mesmo se você der post ele nao grava no banco tem que ser APplyUpdates.

Funciona assim: Voce da Append 10 vezes no ClientDataSet no final vc dar Applyupdates(0). Neste momento ele abra a transacao e tenta gravar os 10  por isso que a gente passa 0 no parametro para dizer qeu aceitamos 0 erro, ou seja, tem que gravar tudo.

Entao nao precisa criar transacao explicita nao.

Att,

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Para finalizar so falta uma coisa , como te disse a estrutura das tabelas são as seguintes   Tb_vendas Id_venda (autoincremento Id_cliente quantidade Valor Data             Tb_items_venda Id_venda id_produto Vl_unidade Qt_itens                           Tb_entregas   Id_venda Id_cliente Vl_compra Nr_entregador data             Observe que nas 3 tabelas eu vou precisar do id_venda . Primeiro eu insiro na Tb_vendas pego o id_venda jogo nuna variável e passo para os outros CDs Existe alguma função interna no clientedataset onde eu possa capturar esse id_venda e jogalo em uma variável ?   Eu fiz um exemplo aqui usando um storedproc , criei uma procedure de insert no SQL Parametro1 Parametro2 @Idvenda int output Insert into Tb_vendas (campos1,campos2,etc) values (parâmetros) Select  @idvenda as identity   Funcionou perfeito pois, a proc insere e traz um retorno , esse retorno eu jogo na variaves e passo para os outros clientdataset  , mas a duvida e a seguinta , fica meio estranho usar clientdatase e stroredproc na aplicação como eu vou captruar esse id usando clientdataset ?      
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Olá CArlos,

Na verdade quando o problema ai e o seguinte, você so terá o ID quando ter o APplyUpdate para dar o ApplyUpdates vc tem que ter o ID  por isso eu sugeri o lance da tabela para gerar o ID mas esta solução com StroredProc ficou muito melhor pois concentra a geração do ID no banco.


Att,


GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Ol´aCarlos,

Podemos encerrar o chamado ??

Att,

GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Ultima pergunta antes de fechar o chamado , trabalhar com storedproc , e clientdataset nao ficaria meio estanho , ou ficaria tudo bem ao seu ver ??????   respode e pode fechar o chamado !
GOSTEI 0
Rodrigo Mourão

Rodrigo Mourão

18/02/2010

Se cada um fizer a sua parte não há problemas.

Por exemplo usar Stored proc para Inserir, Alterar ou Deletar e reinventar a roda. O CDS faz isso automatico. Da mesma forma que usar CDS para Alterar um registro e retorna-lo em seguida nao compensa neste caso a Procedure cai como uma luva.

att,


GOSTEI 0
Carlos Faria

Carlos Faria

18/02/2010

Fecha ai entao ! ok
GOSTEI 0
POSTAR