Gostaria de vê esse mesmo exemplo do video usando o evento OnUpdateRecord do TADQuery, pois já tentei de todas as formas usa-lo e não grava no banco de jeito algum.
Se não usar o evento OnUpdateRecord, funciona 100%
Boas notícias! Recebi um retorno da Embarcadero quanto ao problema do CacheUpdate nos bancos IB e FB. O update 1 do XE5 já vem com a correção do problema!
Mesmo erro do amigo "Olimpio Gonzatto Jr" Sempre usei o Zeos nunca tive problema, para compatibilizar minhas aplicações resolvi usar o bendito firedac que diziam ser top rapido e nativo. Segui o exemplo com sql server e da mesmo problema, não consigo resolver alguem tem a solução ?
[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].
Fiz testes aqui com o Interbase e o Delphi XE6, tudo funcionou certinho… se possível me mandem esses códigos que estão gerando erro para que eu possa reproduzir aqui. Ok!
Consegui simular o erro "[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].". O que ocorre é o seguinte: vocês estão incluindo um registro filho sem antes salvar o registro mestre… segue um link para um vídeo explicando o problema com mais detalhes Ok!
Estou trabalhando com o Firedac e Oracle. E fiquei em uma dúvida em relação ao TFDPhysOracleDriverLink e TFDGUIxWaitCursor.
Esses 2 componentes devem estar presentes em todos os TForm que acessam o Oracle? Se eu utilizar um TDataModule só preciso adicionar apenas um para o projeto todo?
Olá Alan Estou usando o XE7 e mesmo assim estou com o dilema de não conseguir persistir no banco firebird. Habilitei a opção autoincremento na propriedade dos campos pôs o firebird não tem esse tipo de variável. Quando vou gravar não acontece erro nenhum, porém quando faço o refresh os dados somem. Segue o trecho que uso para gravar
if not DTMTabelas.FDConnection.InTransaction then DTMTabelas.FDConnection.StartTransaction; try DTMTabelas.FDConnection.ApplyUpdates([DTMTabelas.QryVenda,DTMTabelas.QryPAF,DTMTabelas.QryItemVenda,DTMTabelas.QryMovimento]); DTMTabelas.FDConnection.Commit; except DTMTabelas.FDConnection.Rollback; end
Gostaria se possível de tirar uma dúvida, estou usando MSSQL e quando dou um post no mestre para inserir os detalhes tenho a exceção [FireDAC][DatS]-15. Duplicate row found on unique index. Constraint [_FD_UC_UniqueConstraint], só dá certo se o dataset mestre estiver vazio e eu inserir um registro, se ele está mostrando alguns registros já inseridos e vou inserir mais um, acontece o erro acima, será que é algum erro de índice ou provider flags?
Rafael Campos, se você estiver utilizando o evento "OnUpdateRecord", você deve altera o valor do parâmetro "AAction" dessa forma: AAction := TFDErrorAction.eaDefault;
Por padrão ele vai como TFDErrorAction.eaApplied, entendendo que você vai fazer o post dos dados no banco, pra isso você pode usar o componente TFDUpdateSQL. Para utilizar esse componente eu te recomendo ler a documentação porquê ele tem alguns detalhes e facilitações.
Felipe Garrido, isso está acontecendo porque você adicionou um campo na propriedade "IndexFieldNames" e ele não aceita duplicações. O que você pode fazer é, no evento "OnNewRecord" você adicionar um valor incremental nesse campo index, ex: "MEU_CAMPO_INDEX" := DataSet.RecordCount + 1. Para gerar o valor real desse campo, o que será persistido no banco de dados, você deve utilizar o evento "OnUpdateRecord" e gerar o valor para esse campo em uma transação, assim:
if (ARequest in [TFDActionRequest.arInsert]) then begin DataSet.Edit(); DataSet.FieldByName('MEU_CAMPO_INDEXADO').AsInteger := GeraCampoInc('MEU_CAMPO_INDEXADO'); DataSet.Post(); end; AAction := TFDErrorAction.eaDefault
Mauro, utilizando um webservice Restfull, quando o objeto for serializado, ao invés do atributo "type", o framework vai passar o atributo "ref" que é a referência ao ponteiro do objeto, e assim, entre as requisições, você pode ir trabalhando com o dataset. Se você estiver utilizando Restless, o melhor é você não trabalhar com datasets em memória entre as pontas(cliente/servidor).
No servidor, ex: a tabela de estados pode estar em um dataset que você vai abrí-lo somente na primeira requisição e mantê-lo em uma variável global ou de classe(pode-se utilizar o padrão singleton), lembrando que deve-se tomar cuidado com o acesso concorrente(thread-safe).
Essa prática é melhor utilizada no lado cliente, onde você pode fazer várias alterações nos dados e depois enviar um batch contendo todas as alterações, podendo inclusive ser o "delta".
Olá amigos! Primeiramente gostaria de agradecer a vc Alan pelos excelente post. Tenho uma dúvida. O exemplo funcionou certinho relacionando a tabela master com a detail. Mas tenho a necessidade de mais um relacionamento com a tabela detail e não com a master. Exemplo
Obrigado pela resposta Alan. Mas o problema tá aí! Se ligar com o detail a chave primaria do master e detail (em modo de insert) estrarão -1 assim não deu certo. Na terceira tabela tenho:
Alan, show de bola os posts, obrigado por compartilhar com a comunidade seu conhecimento. Enfim estou passando pelo problema que já foi citado aqui: "Cannot process – no parent row. Constraint [ForeignKeyConstraint]", estou usando XE7 + SQL Server, eu reparei que no video que vc postou sobre esse assunto e realmente ocorre como vc mostrou ou seja caso não tenha dado post no mestre ocorre o erro acima, porém vc realiza o post no grid do mestre com seta pra cima e para baixo, no meu caso aqui o usuario do meu sistema não vai realizar esse procedimento de dar seta pra cima e para baixo…tentei fazer o post no mestre via codigo…QrMestre.Post e mesmo assim o erro persistiu, saberia me dizer como contornar essa situação?
bom depois de bater cabeça,encontrei um post onde se fazia isso no botão "novo" QrMestre.Append; QrMestre.Post; QrMestre.Edit;
na minha opnião não deveria ser isso, pois como se trata de nova inclusão não justifica o edit abaixo, pois dessa forma o estado do dataset passa a não mais ser de insert e sim de edit, o que dependendo da situação pode prejudicar a escrita do codigo, na minha opnião é BUG. Mas enfim funcionou e vou usar o MD no firedac pois vou poupar muitas horas de desenvolvimento com esse modelo.
Boa tarde Alan, parabéns pelo post, esclareceu muito para mim, seria possível você demonstrar como realizar persistência mestre detalhe usando DataSnap/REST? tenho feito vários testes aqui e não estou conseguindo persistir os dados, desde já obrigado.
Alan, achei muito bom, esclarecedor, objetivo esse vídeo.
Parabéns pelas suas qualificações e pela disposição em nos auxiliar, fiquei um bom tempo afastado do Delphi (parei no 7) e estou correndo atrás para me atualizar. Obrigado.
Olá Alan! Desde já agradeço sua preocupação em contribuir com a comunidade desenvolvedora.
Alan, segui todos os seus passos mas estou tendo alguns problemas ao gravar o detalhe, estou utilizando o Delphi Seatle com o banco de dados Firebird 3.0 com seu índice autoincremento nativo, ou seja, sem usar trigger. O meu problema tem sido o mesmo que o pessoal escreveu logo acima, ao executar o applyupdates ele grava o cabeçalho mas não grava os itens, notei também que ao ativar o DataSet Detalhe, automaticamente desmarca o campo fiDetail do Cache que no vídeo diz que devemos marcar. O que pode estar havendo, será falha no próprio FireDAC ? O que posso estar fazendo de errado.
Oi, Alan! Configurei tudo como no vídeo e usei o bloco de código:
qMestre.Append;
qMestre.Post;
qMestre.Edit;
para iniciar a inclusão do mestre. Porém, usar o mesmo código para incluir qDetalhe dá erro durante qDetalhe.Post;
O erro é “Cannnot – no parent row” dizendo não permitir o valor negativo na chave estrageira que aponta para a tabela Mestre.
Este comentário foi removido pelo autor.
Este comentário foi removido pelo autor.
Gostaria de vê esse mesmo exemplo do video usando o evento OnUpdateRecord do TADQuery, pois já tentei de todas as formas usa-lo e não grava no banco de jeito algum.
Se não usar o evento OnUpdateRecord, funciona 100%
Poderia me enviar um exemplo usando esse evento ?
Estou preparando um vídeo com os eventos onUpdateRecord e onUpdateError do componente TADQuery
Estou com problemas no mestre detalhe usando FireBird,
quando uso o Adqry sem Cache funciona normal.
Mas quando habilito o Cache e coloco como no exemplo ele não salva na base e nem da erros
Estou com um exemplo se for o caso posso te enviar !
Boas notícias! Recebi um retorno da Embarcadero quanto ao problema do CacheUpdate nos bancos IB e FB. O update 1 do XE5 já vem com a correção do problema!
Alan, quanto o auto incremento para master detail usando firedac, poderia nos passar um vídeo aula sobre o assunto.
Olá Alan,
Testei o seu exemplo utilizando a versão xe5 update 2 e retorna o seguinte erro:
[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].
Saberia me dizer porque deste erro?
Mesmo erro do amigo "Olimpio Gonzatto Jr" Sempre usei o Zeos nunca tive problema, para compatibilizar minhas aplicações resolvi usar o bendito firedac que diziam ser top rapido e nativo. Segui o exemplo com sql server e da mesmo problema, não consigo resolver alguem tem a solução ?
[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].
Boa tarde Alan…
Estou enfrentando este problema:
[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].
Segui religiosamente seus passo a passo no vídeo, exceto pelo detalhe de estar utilizando o banco firebird e o XE6…
Alguma ideia de qual seria o problema?
Fiz testes aqui com o Interbase e o Delphi XE6, tudo funcionou certinho… se possível me mandem esses códigos que estão gerando erro para que eu possa reproduzir aqui. Ok!
Consegui simular o erro "[FireDAC] [DatS]-16. Cannot process – no parent row. Constraint [ForeignKeyConstraint].". O que ocorre é o seguinte: vocês estão incluindo um registro filho sem antes salvar o registro mestre… segue um link para um vídeo explicando o problema com mais detalhes Ok!
https://dl.dropboxusercontent.com/u/90063499/Erro%20MestreDetalhe%20FireDAC.mp4
Bom dia Alan,
Estou trabalhando com o Firedac e Oracle. E fiquei em uma dúvida em relação ao TFDPhysOracleDriverLink e TFDGUIxWaitCursor.
Esses 2 componentes devem estar presentes em todos os TForm que acessam o Oracle? Se eu utilizar um TDataModule só preciso adicionar apenas um para o projeto todo?
Att,
Mytracelog – Registro de um DBA
http://mytracelog.blogspot.com
Funciona perfeitamente, mas como ficaria esse mesmo exemplo em um ambiente 3 camadas?
Olá Alan
Estou usando o XE7 e mesmo assim estou com o dilema de não conseguir persistir no banco firebird. Habilitei a opção autoincremento na propriedade dos campos pôs o firebird não tem esse tipo de variável. Quando vou gravar não acontece erro nenhum, porém quando faço o refresh os dados somem.
Segue o trecho que uso para gravar
if not DTMTabelas.FDConnection.InTransaction then
DTMTabelas.FDConnection.StartTransaction;
try
DTMTabelas.FDConnection.ApplyUpdates([DTMTabelas.QryVenda,DTMTabelas.QryPAF,DTMTabelas.QryItemVenda,DTMTabelas.QryMovimento]);
DTMTabelas.FDConnection.Commit;
except
DTMTabelas.FDConnection.Rollback;
end
Este comentário foi removido pelo autor.
Parabéns pelo video, me ajudou muito.
Gostaria se possível de tirar uma dúvida, estou usando MSSQL e quando dou um post no mestre para inserir os detalhes tenho a exceção [FireDAC][DatS]-15. Duplicate row found on unique index. Constraint [_FD_UC_UniqueConstraint], só dá certo se o dataset mestre estiver vazio e eu inserir um registro, se ele está mostrando alguns registros já inseridos e vou inserir mais um, acontece o erro acima, será que é algum erro de índice ou provider flags?
Rafael Campos, se você estiver utilizando o evento "OnUpdateRecord", você deve altera o valor do parâmetro "AAction" dessa forma: AAction := TFDErrorAction.eaDefault;
Por padrão ele vai como TFDErrorAction.eaApplied, entendendo que você vai fazer o post dos dados no banco, pra isso você pode usar o componente TFDUpdateSQL. Para utilizar esse componente eu te recomendo ler a documentação porquê ele tem alguns detalhes e facilitações.
Felipe Garrido, isso está acontecendo porque você adicionou um campo na propriedade "IndexFieldNames" e ele não aceita duplicações. O que você pode fazer é, no evento "OnNewRecord" você adicionar um valor incremental nesse campo index, ex: "MEU_CAMPO_INDEX" := DataSet.RecordCount + 1. Para gerar o valor real desse campo, o que será persistido no banco de dados, você deve utilizar o evento "OnUpdateRecord" e gerar o valor para esse campo em uma transação, assim:
if (ARequest in [TFDActionRequest.arInsert]) then
begin
DataSet.Edit();
DataSet.FieldByName('MEU_CAMPO_INDEXADO').AsInteger := GeraCampoInc('MEU_CAMPO_INDEXADO');
DataSet.Post();
end;
AAction := TFDErrorAction.eaDefault
Sakamoto, basta declarar um único local, geralmente deixo junto à declaração da conexão com o banco.
Este comentário foi removido pelo autor.
Mauro, utilizando um webservice Restfull, quando o objeto for serializado, ao invés do atributo "type", o framework vai passar o atributo "ref" que é a referência ao ponteiro do objeto, e assim, entre as requisições, você pode ir trabalhando com o dataset. Se você estiver utilizando Restless, o melhor é você não trabalhar com datasets em memória entre as pontas(cliente/servidor).
No servidor, ex: a tabela de estados pode estar em um dataset que você vai abrí-lo somente na primeira requisição e mantê-lo em uma variável global ou de classe(pode-se utilizar o padrão singleton), lembrando que deve-se tomar cuidado com o acesso concorrente(thread-safe).
Essa prática é melhor utilizada no lado cliente, onde você pode fazer várias alterações nos dados e depois enviar um batch contendo todas as alterações, podendo inclusive ser o "delta".
Olá amigos! Primeiramente gostaria de agradecer a vc Alan pelos excelente post. Tenho uma dúvida. O exemplo funcionou certinho relacionando a tabela master com a detail. Mas tenho a necessidade de mais um relacionamento com a tabela detail e não com a master. Exemplo
MASTER–>DETAIL–>3º TABELA
Isso é possível utilizando cache?
Obrigado
Sorrilha
Mesmo procedimento, faça o relacionamento do seu novo dataset com o Detail e não esqueça de apontar o SchemeAdapter neste novo Dataset Ok!
Obrigado pela resposta Alan. Mas o problema tá aí! Se ligar com o detail a chave primaria do master e detail (em modo de insert) estrarão -1 assim não deu certo. Na terceira tabela tenho:
id_master (-1)
id_detail (-1)
id_terceira_tabela (identy)
o relacionamento grava com -1
Obrigado mais uma vez.
Alan, show de bola os posts, obrigado por compartilhar com a comunidade seu conhecimento.
Enfim estou passando pelo problema que já foi citado aqui: "Cannot process – no parent row. Constraint [ForeignKeyConstraint]", estou usando XE7 + SQL Server, eu reparei que no video que vc postou sobre esse assunto e realmente ocorre como vc mostrou ou seja caso não tenha dado post no mestre ocorre o erro acima, porém vc realiza o post no grid do mestre com seta pra cima e para baixo, no meu caso aqui o usuario do meu sistema não vai realizar esse procedimento de dar seta pra cima e para baixo…tentei fazer o post no mestre via codigo…QrMestre.Post e mesmo assim o erro persistiu, saberia me dizer como contornar essa situação?
bom depois de bater cabeça,encontrei um post onde se fazia isso no botão "novo"
QrMestre.Append;
QrMestre.Post;
QrMestre.Edit;
na minha opnião não deveria ser isso, pois como se trata de nova inclusão não justifica o edit abaixo, pois dessa forma o estado do dataset passa a não mais ser de insert e sim de edit, o que dependendo da situação pode prejudicar a escrita do codigo, na minha opnião é BUG. Mas enfim funcionou e vou usar o MD no firedac pois vou poupar muitas horas de desenvolvimento com esse modelo.
Boa tarde Alan, parabéns pelo post, esclareceu muito para mim, seria possível você demonstrar como realizar persistência mestre detalhe usando DataSnap/REST? tenho feito vários testes aqui e não estou conseguindo persistir os dados, desde já obrigado.
Alan, achei muito bom, esclarecedor, objetivo esse vídeo.
Parabéns pelas suas qualificações e pela disposição em nos auxiliar, fiquei um bom tempo afastado do Delphi (parei no 7) e estou correndo atrás para me atualizar. Obrigado.
Olá Alan! Desde já agradeço sua preocupação em contribuir com a comunidade desenvolvedora.
Alan, segui todos os seus passos mas estou tendo alguns problemas ao gravar o detalhe, estou utilizando o Delphi Seatle com o banco de dados Firebird 3.0 com seu índice autoincremento nativo, ou seja, sem usar trigger. O meu problema tem sido o mesmo que o pessoal escreveu logo acima, ao executar o applyupdates ele grava o cabeçalho mas não grava os itens, notei também que ao ativar o DataSet Detalhe, automaticamente desmarca o campo fiDetail do Cache que no vídeo diz que devemos marcar. O que pode estar havendo, será falha no próprio FireDAC ? O que posso estar fazendo de errado.
Agradeço
Oi, Alan! Configurei tudo como no vídeo e usei o bloco de código:
qMestre.Append;
qMestre.Post;
qMestre.Edit;
para iniciar a inclusão do mestre. Porém, usar o mesmo código para incluir qDetalhe dá erro durante qDetalhe.Post;
O erro é “Cannnot – no parent row” dizendo não permitir o valor negativo na chave estrageira que aponta para a tabela Mestre.
Tens alguma luz pra me ajudar, pfv?
Po, Alan. Era um problema interno. Resolvido!