PASSO-A-PASSO COMO CRIAR UM RELACIONAMENTO MASTER/DETAIL USANDO CLIENTDATASET

TODAS AS TABELAS ENVOLVIDAS NESTE PROCESSO TEM QUE TER CHAVE PRIMÁRIA E ESTRANGEIRA, DO CONTRARIO ISTO DAÍ NÃO VAI FUNCIONAR 100% ESTÁVEL.

2) Coloque um componente TADOConnection no seu DataModule e defina as configurações devidas nele.

3) Coloque um compoente TQuery no Datamodule ou então um TSQLDataSet. Vamos Chamá-lo de qMaster, ou sqldMaster.

4) Coloque na propriedade SQL do qMaster, ou então na propriedade CommandText do sqldMaster a sentença SQL que você deseja buscar como dados da Tabela Master.

5) Dê um clique duplo na qMaster. Aparecerá o FieldsEditor. Manda adicionar todo mundo.

6) Em cada TField, localize a propriedade providerflags. Os campos que são chave primária na Tabela, ficarão com pfInkey true nos, os demais ficou false. Os pfInUpdate e pfInWhere todos ficam como true (em todos os campos). o pfInkey informa ao seu Componente, quais campos são chave primária na tabela.

NOTA: Caso você queira fazer um Join com uma ou mais tabelas mas querendo que somente em uma tabela sejam gravados os dados, você deverá marcar o campo ReadOnly para true NOS CAMPOS DAS TABELAS QUE NÃO PERTENÇAM A TABELA QUE SERÁ GRAVADA.

7) Coloque um componente TDatasetProvider no Datamodule. vamos chamá-lo de dspMaster.

8) Aponte o Dataset dele pra qMaster ou pro sqldMaster.

9) Abra a propriedade Options do dspMaster. Todas as subpropriedades dele devem ficar como false, exceto as poCascadeDeletes, poCascadeUpdates, poAutoRefresh, poPropogateChanges, poRetainServerOrder Estas tres deverão ficar setadas como True.

Significado das propriedades:

poCascadeDeletes: Propaga a deleção para os registros Detail. Para esta opção funcionar, sua tabela deverá ter esta configuração nas diretivas da chave de integridade referencial no detail

poCascadeUpdates: Propaga a atualização para os registros Detail. Para esta opção funcionar, sua tabela deverá ter esta configuração nas diretivas da chave de integridade referencial no detail

poAutoRefresh: Propaga a atualização da Query para os ClientDataset automaticamente quando as atualizações são feitas através do evento onApplyUpdates.

poPropogateChanges: As atualizações feitas através dos eventos BeforeUpdateRecord ou de AfterUpdateRecord serão propagadas posteriormente para os ClientDatasets.

poRetainServerOrder: Reestabelece automaticamente, a ordenação dos dados no ClientDataset.

Mais informações, consulte o help do Delphi sobre "TProviderOption, TProviderOptions type"

10) Mude a propriedade, no dspMaster, UpdateMode para "upWhereKeyOnly"

11) Coloque no seu Datamodule um componente TClientDataset. Vamos chamalo de cdsMaster.

12) Aponte o Provider dele pra dspMaster.

13) Ative o cdsMaster, mudando a propreiedade Active dele para True. Dê um clique duplo na cdsMaster. Aparecerá o FieldsEditor. Manda adicionar todo mundo.

14) Repita o passo 6. Mas agora, você pode formatar os campos. Na propriedade DisplayLabel, coloque um nome mais legível ao usuário. Na propriedade Displayformat, você pode formatar valores monetários e de data para serem exibidos. Na propriedade EditFormat voce pode formatar estes valores para serem editados no cadastro. A propriedade Visible do TField, permite você ocultar este campo nos DBwares.

15) Coloque no seu DataModule, um componente TDataSource. Vamos chama-lo de dsMaster.

16) Aponte o Dataset dele para o cdsMaster.

Seu Módulo Master está pronto.

Agora vamos linkar ele ao Modulo detail.

1) Coloque no seu DataModule, um componente TDataSource. Vamos chama-lo de dsMasterDetail.

2) Aponte o Dataset dele para o dsMaster.

3)Coloque um compoente TQuery no Datamodule ou então um TSQLDataSet. Vamos Chamá-lo de qDetail, ou sqldDetail.

4) Coloque na propriedade SQL do qMaster, ou então na propriedade CommandText do sqldMaster a sentença SQL que você deseja buscar como dados da Tabela Detail, com o detalhe de que o parametro de referência na tabela detail, deve ter OBRIGATÓRIAMENTE o nome exato do campo chave na tabela master. Veja o exemplo:

Na tabela master queremos buscar todas as MM (movimentação de material) de um determinado amoxarifado:

select IDMOV, CODTMV, SERIE, NUMEROMOV, DATAEMISSAO, DATAENTREGA,
COMPETENCIA, CODFILIAL, CODPESSOA, CODLOCALIDADE,
CODOSATIV, CODCONTRATO, CODLOC, CODFILIALDEST, CODLOCDEST, STATUS,
OBSERVACAO, USRCRIACAO, DATACRIACAO, USRALTERACAO,
DATAALTERACAO, DATAEXPORTACAO, NOMEARQEXPORT, CODCCUSTO, CODDEPTO, CODAREA
from ZMMTMOV

Na tabela detail, queremos buscar todos os itens da MM (movimentação de material) de um determinado registro master:

select IDMOV, NSEQITMMOV, IDPRD, QUANTIDADE, CODUND, LOTE, ROLO, PATRIMONIO
from ZMMTITMMOV where IDMOV = :IDMOV

ATENTE PARA O PARÂMETRO IDMOV. ELE É O MESMO NOME DO CAMPO MASTER IDMOV.

5) repita os passos 5 e 6 da geração da query master (referentes ao Tfieds).

6) Sete a propriedade CursorLocation da qDetail ou do sqldDetail pra "clUseClient"

7) Repita o passo 8 da geração da query master (referentes ao parametro).

8) Aponte o Datasource de qDetail para o dsMasterDetail.

9) Repita o passo 15 do cdsMaster, só que agora, ao você mandar adicionar os TFields, irá aparecer um novo campo. Este campo é um DATASETFIELD é o elo de comunicação entre o seu master e o detail e deverá ter o nome qDetail.

10) No cdsDetail, aponte o seu Datasetfield para qDetail.

11) Repita o passo 16 do cdsMaster para o cdsDetail. Mesma coisa.

Está pronta a sua tão sonhada conexão MD.

Você pode criar ainda Details que sejam detail deste ultimo Detail que criamos agora. Para fazer isto, basta fazer o seguinte:

1) Coloque no seu DataModule, um componente TDataSource. Vamos chama-lo de dsDetailDetail.

2) Aponte o Dataset dele para o dsDetail.

O resto dos procedimentos, você pode seguir os passos da criação do CDS e do Datasource. A unica diferença é que pra este novo caso (Detail de um Detail mestre), não é necessário um novo DatasourceProvider.

E assim você pode fazer relacionamento MD em cascata ou em arvore mesmo. Só tome o cuidado pra não fazer bagunça e depois a coisa ficar inviável pra dar manutenção.

Para fazer uma inclusão ou uma edição em um relacionamento MD: você deve dar insert/Edit em todos os Datasets. Para dar o post, dê post apenas nos details, NO MASTER PRINCIPAL SOMENTE DAR O APPLYUPDATES DIRETO. Não dê applyUpdates em algum detail.

Para fazer uma exclusão em um relacionamento MD: você deve dar delete em todos os Datasets, SOMENTE NO MASTER DAR O APPLYUPDATES DEPOIS DO DELETE. Não dê applyUpdates em NENHUM detail.

1) Sugestão de código para você dar um ApplyUpdates no Dataset:

Deve ser colocado nos eventos: onAfterPost e onAfterDelete do ClientDataSet:

 if (DataSet as TClientDataSet).ApplyUpdates(0) <> 0 then
  raise EDataBaseError.Create(Exception(exceptobject).Message)
 else
  (DataSet as TClientDataSet).Refresh;

2) Sugestão para abertura do ClientDataset ordenado:

Deve ser colocado no evento onBeforeOpen do ClientDataSet:
 (DataSet as TClientDataSet).indexname := 'DEFAULT_ORDER';

3) Ativar o ReconcileError em todos os ClientDatasets do DataModule:
Declare na cláusula Private do DM:
 procedure CdsReconcileError(
 (*$IFDEF VER150*)
  DataSet: TCustomClientDataSet;
 (*$ELSE*)
  DataSet: TClientDataSet;
 (*$ENDIF*)
  E: EReconcileError; UpdateKind: TUpdateKind;
 var Action: TReconcileAction);

Em seguida, no Evento onCreate do DM, coloque o seguinte código:
 for i := 0 to ComponentCount-1 do
 begin
  if Components[i] is TClientDataSet then
   TClientDataSet(Components[i]).OnReconcileError := CdsReconcileError;
 end;

4) Gerar o formulário de cadastro já pronto pra ser utilizado.

  a)Crie um novo form.

  b)Coloque um DBNavigator nele ou um outro componente de navegação na tabela.

  c)Dê um clique duplo no CDS referente aquele cadastro e deixe aberto o Fields Editor

  d)Minimize outras telas de forma a deixar o Fields Editor emparelhado com o form. Marque todos os TFields

  e) Arraste todos eles ou um a um para o form. Já será criado o Label com o DBEdit e o Datasource refernte aquele Dataset.



E-Mail: walterchagas@yahoo.com Clique aqui para cair fora desta pagina.