GARANTIR DESCONTO

Fórum Inserção com MasterSource e MasterFields #313520

20/02/2006

0

Pessoal,

Uso os componentes datasource, dataset provider, client datasets, SQLDatasets e SQLConnection. Suponham que eles estejam conectados corretamente.

Tenho um clientdataset ´A´ que representa uma tabela ´revista´, e outro ´B´, que representa uma tabela ´reportagem´.

A propriedade MasterSource do ´B´ aponta para o ´A´ e o masterfield contém o relacionamento entre as duas tabelas.

Quando eu insiro um novo registro, no mesmo form eu insiro os dados da revista e já adiciono todas as reportagens que ela contém. Ou seja, nessa situação a revista está sendo inserida juntamente com as reportagens dela.

O problema é que quando eu salvo, aparece um erro dizendo que o campo ´cod_revista´, do ´B´, deve ter um valor ( ´cod_revista must have a value´ ), porém, ele já está no relacionamento do masterfields !

Quando eu estou em modo de edição, funciona perfeito, pois a chave primária de ´revista´ já existe.

Uso Firebird 1.5 com generator + trigger para criação de chaves primárias.

Resumindo: como eu posso inserir um novo registro, utilizando a estrutura de form que eu citei (cadastro da revista e das reportagens ao mesmo tempo), utilizando MasterSource/MasterFields ? Devo utilizar outro método para isso?

Obrigado, pessoal !


Marcelocda

Marcelocda

Responder

Posts

20/02/2006

Rafael Gomes

caro marcelo ...
para que voce possa inserir os registros detalhes com sucesso, a chave primaria da sua tabela mestre DEVE ter um valor. se nao tiver como o delphi vai relacionar as duas tabelas????

no modo de edição, creio que voce ja inseriu o registro no banco de dados e o valor da chave primaria ja existe, logo nao terá problemas para inserir os registros detalhes ...

creio que vc esta querendo inserir os registros detalhe sem antes dar um post na sua tabela mestre.

se nao for isso volte a postar!!
[]s


Responder

Gostei + 0

21/02/2006

Marcelocda

Obrigado por sua resposta, Rafael !

a estrutura aqui está da seguinte forma:
1) Dou um Post no cds mestre (somente uma vez, testando se o estado dele está em dsInsert ou dsEdit) ao adicionar uma reportagem
2) Dou um Post no cds detalhe para cada reportagem adicionada
3) Na hora de salvar, eu faço um applyupdates(-1) no cds mestre e em seguida outro no cds detalhe

Continua dando o mesmo erro :(

Será que isso tem a ver com o fato de eu utilizar um generator junto com um trigger para a geração de chaves primárias ?


Responder

Gostei + 0

21/02/2006

Marcelocda

Sobe...


Responder

Gostei + 0

22/02/2006

Marcelocda

Alterei o algoritmo para o código abaixo, que é executado ao clicar no Salvar:

  dModule.IniciaTransacao();

            dModule.cdsReportagem.Post;
            dModule.cdsExemplar.Post;

            dModule.cdsExemplar.ApplyUpdates(-1);
            dModule.cdsExemplar.Refresh;

            dModule.cdsReportagem.Edit;
            dModule.cdsReportagemCOD_EXEMPLAR.AsInteger := dModule.cdsExemplarCOD.AsInteger;
            dModule.cdsReportagem.ApplyUpdates(-1);

            dModule.Commit();


Bem, pessoal, o que está acontecendo é o seguinte:
1. Continua dando o mesmo erro, mesmo eu salvando o mestre primeiro.
2. Após o Refresh do cds mestre, como pude comprovar no debug, ele realmente está atribuindo o código gerado ao campo COD_EXEMPLAR, do cds detalhe. Porém, ao salvar o cds detalhe, ele continua acusando que COD_EXEMPLAR é null.

E uma coisa muito estranha que acontece:
a) No meu generator o valor corrente é 29, porém, o valor que está sendo atribuído ao COD do cds mestre é 6. Por quê isso acontece?

Após encontrar o mesmo erro, eu tentei atribuir o código ´na mão´, como foi visto na penúltima linha, antes do applyupdates do cds detalhe, e mesmo assim, continua acusando o erro de NULL no COD_EXEMPLAR.

O update mode está como UpWhereKeyOnly.

Por favor, pessoal, alguém poderia me dizer o que está errado?


Responder

Gostei + 0

22/02/2006

Paullsoftware

a) No meu generator o valor corrente é 29, porém, o valor que está sendo atribuído ao COD do cds mestre é 6. Por quê isso acontece?


vc está apontando os campos corretos no código do gerador??

tipo, o código da minha Trigger é esse:
CREATE TRIGGER CLIENTES_BI FOR CLIENTES
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.CODIGO IS NULL) THEN
    NEW.CODIGO = GEN_ID(GEN_CLIENTES_ID,1);
END


só um detalhe, como está o valor [b:00fa1136fa]Default[/b:00fa1136fa] do seu campo código, tente incluir dados pelo próprio banco e veja se o [b:00fa1136fa]GERADOR [/b:00fa1136fa] esta funcionando, uma vez aconteceu comigo de não funcionar, mais por que o [b:00fa1136fa]Default[/b:00fa1136fa] do campo código estava 0...

Post aqui o resultado!


Responder

Gostei + 0

22/02/2006

Emerson Nascimento

tente algo assim:
dModule.IniciaTransacao(); 

            dModule.cdsReportagem.Post; 
            dModule.cdsExemplar.Post; 

            dModule.cdsExemplar.ApplyUpdates(-1); 
            dModule.cdsExemplar.Refresh; 

            dModule.cdsReportagem.First; // primeiro registro
            while not dModule.cdsReportagem.Eof do
            begin
              dModule.cdsReportagem.Edit; 
              dModule.cdsReportagemCOD_EXEMPLAR.AsInteger := dModule.cdsExemplarCOD.AsInteger;
              dModule.cdsReportagem.Post; // grava o valor do "mestre"
              dModule.cdsReportagem.Next; // passa para o próximo registro
            end; 
            dModule.cdsReportagem.ApplyUpdates(-1); // aplica as alterações

            dModule.Commit();

veja se assim dá certo. o problema está no fato de a ligação master/detail não ter (infelizmente) o recurso de [i:7d955c1fd1]propagate changes[/i:7d955c1fd1] do nesteddataset. de qualquer forma faça o teste e nos avise sobre o resultado.


Responder

Gostei + 0

22/02/2006

Marcelocda

Bem, eu resolvi adotar a seguinte solução: como eu já estou usando trigger, eu coloquei a definição do código do exemplar da reportagem dentro dele. Assim, passou a funcionar.

De qualquer forma, a lógica do Émerson está correta. Só que no meu caso eu teria que fazer umas coisas chatas no clientdataset, como achar o registro que acabou de ser inserido e filtrar o cds detalhe, já que nos meus cds estão todos os registros, pois também os utilizo para visualização em grid. Não sei se isso é trivial, porém, não quis perder mais tempo com isso.

Agora cá entre nós, essa implementação de mestre-detalhe no Delphi é bizarra, hein? Não propagar o valor da chave primária que foi inserida...Acaba servindo apenas para listagem e filtro mesmo.

PaullSoftware, o generator e o trigger estão corretos :)
Obrigado pelas respostas de todos !

São esses detalhes que eu busco nos livros e não acho...Coisas como a não propagação dos valores do cds mestre, contidos em um relacionamento mestre-detalhe;
No geral, os livros de delphi que vejo são muito superficiais...

Se alguém puder me indicar um livro BOM mesmo, que tenha um nível de detalhes desse tipo...Ficaria muito agradecido !

Valeu, pessoal !

Obrigado a todos e em especial ao Émerson !


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar