Mestre/Detalhe amp; Commit?

Delphi

09/06/2008

Bom dia brothers!!!

Eu estou acostumado a trabalhar com relacionamento Mestre/Detalhe, porem encontrei um problema que até agora não consegui resolver.

Uso Delphi 2007, Firebird 2.0 com MDO e aplicação com jalenas MDI.

A bronca maior é o fato de eu [b:7454fe04fa]não [/b:7454fe04fa]estar utilizando o [b:7454fe04fa]CommitRetaining [/b:7454fe04fa]como de costume.

Minhas tabelas:

[b:7454fe04fa]Produtos(Cod,Descricao,Modelo)

Produtos_Acessorios(Cod,Qtde,Cod_Produto,Cod_Acessorio)

Acessorios(Cod,Descricao,Valor)[/b:7454fe04fa]

Cada produto é composto por N acessórios, no qual o preço final será composto pela soma de acessoriosXquantidade de cada um.

Antes eu sempre aplicava um Post/CommitRetaining no cadastro do produto para efetivar os dados na tabela, para após isso eu incluir os Acessórios no Grid que é exibido dentro do form de cadastro do Produto.

Agora, quando eu abro o form de cadastro eu tenho uma transação e esta só é finalizada atraves de Commit, eu estou tentando adicionar os acessorios com essa transação aberta, pois caso seja cancelado, nada fique registrado, por exemplo um produto sem acessorios.

Minha dúvida é: como manter essa transação mestre aberta (mesmo sem ter gravado o registro mestre) e incluir dados na tabela detalhe e exibi-los no grid atualizando a cada novo acessorio incluido/excluido, e efetivar todas essas operações somente depois do commit?

abraços


Eniorm

Eniorm

Curtidas 0

Respostas

Eniorm

Eniorm

09/06/2008

sobe


GOSTEI 0
Eniorm

Eniorm

09/06/2008

up


GOSTEI 0
Brunodsr

Brunodsr

09/06/2008

Não sei se entendi bem, mas acho que vc tá meio confuso com o lance de transação.

Qndo vc abre uma transação no banco de dados, ele reserva um espaço p/ vc fazer o que quiser: deletar registros, incluir novos, alterar e tudo o mais.

Essa transação será fechada apenas quando vc confirmar os seus comandos ou cancelá-los (commit e rollback). Até lá, os registros modificados ficarão locados ou não com vc (snapshot, readcommited etc).

O commit retaining é uma forma de confirmar as alterações no banco e manter a mesma transação aberta. É tipo uma parcial das suas alterações. É muito usado para commitar grupos de modificações.

No seu caso, vc não precisa comitar a cada post. Isso pode ser feito apenas no final e sem problemas. O master-detail não impede que vc grave cabeçalho e ítens.

Usando o dbexplorer, faça o seguinte:
1. Abra uma transação:
2. Insira os dados do cabeçalho;
3. Insira os dados dos ítens do cabeçalho;
4. Cancele (rollback).

Verifique que os dados não foram gravados.

Espero ter ajudado.


GOSTEI 0
Eniorm

Eniorm

09/06/2008

cara, deu uma clareada, mas o meu problema principal é ir exibindo cada item adicionado no detalhe

ou seja, para cada item que eu adiciono eu tenho que exibir no dbgrid

na query desse grid eu uso o SQL trazendo dados das duas tabelas relacionadas e de acordo com o cod do mestre

abraços


GOSTEI 0
Brunodsr

Brunodsr

09/06/2008

No momento em que vc faz o inser + post no mestre, ele já tem ID. Isso é independente de generator, unique ou o que for.

Faça o seguinte teste.. Daí vc ver na prática o que eu to falando.

1. Abra um form zerado;
2. Inicie a transacao no momento em que ele for criado;
3. Coloque uns 5 ´INSERT INTO TABELA´ na sua query;
4. Coloque um botao para executar ele;
5. Ponha um grid na tela e ligue ele a outro dataset que tem um ´SELECT * FROM TABELA´;
6. Coloque outro botao para executar a segunda query;
7. IMPORTANTE: Se certifique que as duas queries estao na mesma transacao;
8. Coloque um botao na tela;
9. Na programacao dele coloque um rollbackretaining.

Com isso ai vc vai ver que todos os inserts que vc deu sao visualizados no banco (dentro da mesma transacao) e que quando vc cancela elas (rollback), os registros desaparecem.

Use isso para preenher seu cabecalho e itens:
1. Insert na tabela pai;
2. Insert nos filhos; (select no pai para pegar o codigo)
3. Depois de lancar tudo, commit.

Eu sei q fica foda de assimilar sem ver rodando.. entao, se vc quiser um exemplo pratico, me passa um email e eu te passo um blz?


GOSTEI 0
Eniorm

Eniorm

09/06/2008

saudações Bruno, com essas suas explicações eu consegui visualizar o cenário completo em funcionamento rsrsrs acho que agora consigo implementar as idéias.

irei testar e posto os resultados

obrigado pela ajuda


GOSTEI 0
Eniorm

Eniorm

09/06/2008

rapaz.... fiz como vc disse e não funcionou, procedi da seguinte forma

StartTransaction;
DataSetMestre.Insert;
DataSetDetalhe.Insert;
Incluo a PK da tabela Mestre;
Incluo a PK da tabela de Itens;
Post;
QueryExibeDetalhes.Close;
Incluo o parâmetro PK da tabela Mestre;
QueryExibeDetalhe.Open;


Todos esses componentes estão associados ao mesmo objeto Transaction, configurado para o nível de isolamento ReadCommited, mas tentei as 4 opções do componente e nenhuma funcionou.

Estranho: após o Post, inclui um ShowMessage para exibir o RecordCount do DataSetDetalhe, o mesmo indicava registros adicionados.

Porem, a query que deveria exibir os detalhes não exibe;

Bruno, se vc me puder passar o exemplo, meu email é: eniorm@gmail.com

ou para facilitar, caso vc queira, deixe disponível num ftp para que outros possam pegar,

vc pode usar esse que é de onde eu trabalho:
ftp.santafedosul.sp.gov.br/publico/


cordialmente,


GOSTEI 0
Eniorm

Eniorm

09/06/2008

brothers, fiz uma pequena aplicação para teste, bem simples, usando MDO e que tbm não funcionou como esperado

caso alguém queira dar uma olhada, deixei disponível para download no link abaixo

[url]ftp.santafedosul.sp.gov.br/publico/Teste_MasterDetail.rar[/url]

abraços


GOSTEI 0
Eniorm

Eniorm

09/06/2008

up


GOSTEI 0
Brunodsr

Brunodsr

09/06/2008

Ola Enio.

Estive doente nos ultimos dias(bronquite) e so to vendo o seu post hoje.

Vou fazer um exemplo do jeito que eu te falei e te dou um toque blz?

Um abraco,


GOSTEI 0
Eniorm

Eniorm

09/06/2008

blza brother, se quiser ver esse exemplo que eu postei, foi o que eu fiz seguindo as explicações.

abraço


GOSTEI 0
Eniorm

Eniorm

09/06/2008

Saudações amigos,

após uma terrível luta com Transações, consegui implementar de acordo com minhas idéias iniciais (no primeiro post)

quem quiser a aplicação-exemplo está disponível em

[url]ftp.santafedosul.sp.gov.br/publico/Teste_MasterDetail_OK.rar[/url]

o exemplo possui o FDB, está compilado e junto com os sources.

Agradeço a todos que colaboraram para eu conseguir resolver essa bucha!

grande abraço a todos.


GOSTEI 0
Brunodsr

Brunodsr

09/06/2008

Enio,

Eu to com o exemplo q te falei, so n consigo postar no ftp.

Se vc ainda quiser dar uma olhada da um toque blz?


GOSTEI 0
Eniorm

Eniorm

09/06/2008

Enio, Eu to com o exemplo q te falei, so n consigo postar no ftp Se vc ainda quiser dar uma olhada da um toque blz?


Amigos, eis aqui o exemplo criado pelo colega Bruno, deixei no ftp para fácil acesso a todos os interessados:

[url]ftp.santafedosul.sp.gov.br/publico/DataBase.rar[/url]

abraços


GOSTEI 0
Adriano_servitec

Adriano_servitec

09/06/2008

Olá amigos, estou com o mesmo problema aqui, ai baixei o programa pra ver, é realmente o que eu preciso, mais no meu caso aqui é mais para alteração então eu fiz na tabela mestre dois cadastros e gravei no banco

Depois na grid detail fiz 3 cadastros e fui gravar e esta gravando apenas o primeiro no banco o resto esta se perdendo, quando dou o commit.


GOSTEI 0
Adriano_servitec

Adriano_servitec

09/06/2008

Desculpe o equivoco, é que eu não estava dando um refresh na tabela detail, agora sim, acho que vai funcionar aqui pra mim tambem

Obrigado pessoal.

Qualquer coisa eu retorno


GOSTEI 0
Adriano_servitec

Adriano_servitec

09/06/2008

Pessoal, estou postando aqui para dizer que eu consegui aqui tambem, ficou da forma que eu desejava. :D

Obrigado [b:3637a76711]brunodsr[/b:3637a76711]

Obrigado [b:3637a76711]Enio Marconcini[/b:3637a76711]

Agora sim esta certo

Valeu pessoal


GOSTEI 0
Adriano_servitec

Adriano_servitec

09/06/2008

Inclusive achei interessante tratar o commit/rollblack no evento onclosequery do form tambem

procedure TfrmAltDEAR.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
 var
  nCode : Word;
begin
  if dm.IBTransaction1.InTransaction then
  begin
    nCode := dc_messageDlg(´Atenção! Foram feitas atualizações e não foram ainda atualizadas.´+#13+
                           ´Deseja atualizar os dados no Banco?´, mtInformation, [mbYes, mbNo], 0);
    case nCode of
      mrYes: dm.IBTransaction1.CommitRetaining;
      mrNo:  dm.IBTransaction1.Rollback;
    end;
  end;
  inherited;
end;


Assim evita do usuario sair sem commitar ou abandonar a operação realizada.


GOSTEI 0
Eniorm

Eniorm

09/06/2008

ehehehe

o que mais me deixou intrigado foi que, após os esclarecimentos do Bruno, tudo oq deveria ser feito tinha ficado claro, bastava reimplementar.

Deu alguns erros de FK (principalmente no momento do ApplyUpdates com CachedUpdates).

Agora está tudo ok, funcionando.

Adriano, qual seria a diferença entre [b:6de5f48436]onClose [/b:6de5f48436]e [b:6de5f48436]onCloqueQuery [/b:6de5f48436]do form


GOSTEI 0
Adriano_servitec

Adriano_servitec

09/06/2008

[quote:42cd835f5c=´Enio Marconcini´]Adriano, qual seria a diferença entre [b:42cd835f5c]onClose [/b:42cd835f5c]e [b:42cd835f5c]onCloqueQuery [/b:42cd835f5c]do form[/quote:42cd835f5c]Olá Enio, bom eu aqui uso forms MDI então no caso se eu fechar o form principal(pai) não vai commitar os dados, então optei por fechar no onCloseQuery, assim aonde o usuario estiver ele vai mostrar a mensagem.

Mais ainda está em teste, não sei bem se vai funcionar certinho, mais por enquanto esta funcionando. :D


GOSTEI 0
Eniorm

Eniorm

09/06/2008

aqui uso forms MDI então no caso se eu fechar o form principal(pai) não vai commitar os dados, então optei por fechar no onCloseQuery, assim aonde o usuario estiver ele vai mostrar a mensagem.


eu tbm estou usando MDI, e no evento OnClose está implementado algo semelhante:

if (InTransaction) then
  MessageDlg(´Deseja gravar...´



GOSTEI 0
POSTAR