Chave primária com ClientDataSet(CDS)
22/11/2005
0
Estava com um problema num projeto da facul, e já estava pra postar aqui, mas agora a coisa ficou pior pq surgiu o mesmo problema no trampo. Preciso de uma rotina segura para a manipulação das chaves primárias no meu banco. Já dei uma pesquisada e o melhor q eu achei foi fazer uma função recursiva q dá um applyupdates com um novo valor de chave qdo dá erro. Porém, não acho q seria o ideal, pois no help eu verifiquei q existe o evento on UpdateError para manipular esse tipo de problema, e me pareceu a melhor solução. Só q eu não entendi como se utiliza esse evento. Se alguem puder me dar uma :idea: eu ficarei muito grato.
Ah... O meu trabalho da facul é um desafio um pouco maior. É um mestre-detalhe. Aí a minha dúvida é a seguinte: Eu posso manipular só a chave do CDS mestre, ou eu preciso fazer isso com o CDS detalhe também.
Muitoi obrigado pela ajuda.
Leomar de Rossi Ferreira
Lero
Posts
22/11/2005
Emerson Nascimento
22/11/2005
Lero
Leomar de Rossi Ferreira.
22/11/2005
Lero
begin cdsAgendaagenda_id.NewValue := StrToInt(VarToStr(cdsAgendaagenda_id.Value)) + 1; Response := rrApply; end;
O problema é q qdo ele vai setar o NewValue, ele dá um erro de ´Falha Catastrófica´. Como faço para setar a NewValue corretamente? Acho q se conseguir setar o problema tá resolvido. Qualquer ajuda serve, por favor.
Leomar de Rossi Ferreira
22/11/2005
Emerson Nascimento
22/11/2005
Lero
Ahhh... Eu tô dando o ApplyUpdates dentro de uma transação, claro. A transação impediria a colocação de duas chaves com o mesmo valor ao mesmo tempo? Quero dizer, se eu indicar o valor no UpdateRecord e o DSP aplicar o insert sem erro, outro cliente q busque a chave após o insert, mas durante a transação antes do commit vai ter retornado qual valor? De qualquer forma ainda poderia haver erro, pois o outro cliente pode pegar o valor antes do insert, mas é uma dúvida q eu tenho há algum tempo.
Leomar de Rossi Ferreira
22/11/2005
Emerson Nascimento
por exemplo:
usuario A inseriu. codigo 1;
usuario B inseriu. codigo 2;
usuario B gravou; codigo 2;
usuario A cancelou;
dessa forma pode acontecer de ficarem ´buracos´ entre os códigos.
se a atribuição for feita somente no momento da gravação (o ukInsert do OnUpdateRecord só acontece no momento do ApplyUpdates, porque o provider só reconhece a inserção no momento em que ela for descarregada para o HD)
usuario A inseriu.
usuario B inseriu.
usuario C inseriu.
usuario B gravou; codigo 1;
usuario A cancelou;
usuario C gravou; codigo 2;
23/11/2005
Lero
Acho q não entendi direito. No exemplo q vc deu se o usuário A cancela a gravação e o B grava, a chave do registro do B seria 1, mas se o A gravasse, a chave seria 2 para o B. O q eu não entendi é como eu faço pro cliente receber um valor de chave único sendo q ainda não foi gravado no banco. Eu não sei como se faz isso, se vc puder me dar uma orientação, eu agradeço.
Ah... Eu não achei o evento [b:8404ba2482]onUpdateRecord[/b:8404ba2482], no [b:8404ba2482]DataSetProvider[/b:8404ba2482] só tem [b:8404ba2482]BeforeUptdateRecord e AfterUpdateRecord[/b:8404ba2482]. No CDS tb não tem, nem no ADODataSet q está ligado ao provider. Em qual componente ele fica? (o meu Delphi é o 7)
De qualquer forma, acho q o ideal pra mim seria utilizar o [b:8404ba2482]OnUpdateError[/b:8404ba2482], só q qdo eu tento alterar o [b:8404ba2482]TField.NewValue[/b:8404ba2482] ele dá erro de [b:8404ba2482]´Falha Catastrófica´[/b:8404ba2482] :shock: . Tô achando q esse problema é por causa da mistura explosiva ADO + DSP + CDS. Alguém já teve esse problema?
23/11/2005
Emerson Nascimento
agora, para poder te ajudar de forma satisfatória, como você adquire o valor da chave? pega o último valor e soma um, ou tem uma tabela que controla a numeração?
23/11/2005
Lero
23/11/2005
Emerson Nascimento
procedure TForm1.DataSetProvider1BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); var proximocodigo: integer; begin case UpdateKind of ukInsert: if SourceDS = SeuADODataset then begin // pega o próximo codigo with ADODataset_geral do begin close; commandtext := ´select max(codigo) from tabela [where...]´; open; if fields[0].isnull then proximocodigo := 1 else proximocodigo := fields[0].asinteger + 1; close; end; DeltaDS.FieldByName(´codigo´).newvalue := proximocodigo; end; end; end;
adicione a opção poPropagateChanges na propriedade Options do Provider para que o novo código seja exibido no seu dataware após a gravação.
24/11/2005
Lero
Mais uma vez, muito obrigado pela sua colaboração.
Leomar de Rossi Ferreira
24/11/2005
Emerson Nascimento
- os valores serão atribuídos somente na execução do applyupdates.
- só haverá intervalos se por acaso vc estiver no código 5 e algum usuário excluir o registro 3. obviamente o próximo será o 6 e o haverá o ´buraco´ do 2 para o 4.
sinceramente eu nunca soube o porquê de controlar isso. geralmente o campo-chave é invisível para o usuário. é utilizado internamente, principalmente para relacionamento entre tabelas.
em tempo: para sua maior comodidade eu sugiro ainda que você trabalhe com tabelas aninhadas. as famosas nested tables.
Clique aqui para fazer login e interagir na Comunidade :)