Erro ao aplicar o Delta manualmente usando BeforUpdateRecord

Delphi

26/07/2006

Estou usando Delphi 7 + Firebird 1.5 + DbExpress.

Tenho uma query na qual faço um join e quero aplicar a cache (delta) manualmente.
Seguindo o exemplo da ClubeDelphi nº 25, descobri que tenho que utilizar o evento BeforUpdateRecord do Provider.
Fiz conforme no exemplo e a opção de exclusão funcionou normalmente, mas a opção de alteração só me retornava o erro [b:9af8697e7f]Unexpected end of command[/b:9af8697e7f].
Após exaustivas tentativas, peguei um pequeno exemplo à parte do projeto, onde tentei aplicar a cache em apenas uma tabela - ocorreu o mesmo problema - a exclusão funciona, mas a alteração da o erro acima.
Segue o código:

procedure TDataModule1.DSPFilialBeforeUpdateRecord(Sender: TObject;
  SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
  UpdateKind: TUpdateKind; var Applied: Boolean);
begin
  case UpdateKind of
    ukDelete:
    begin
      ShowMessage(´DELETE FROM FILIAL WHERE CODIGO = ´ + DeltaDS.FieldByName(´CODIGO´).AsString);
      SQLConnect.ExecuteDirect(´DELETE FROM FILIAL WHERE CODIGO = ´ + DeltaDS.FieldByName(´CODIGO´).AsString);
    end;
    ukModify:
    begin
      ShowMessage(´UPDATE FILIAL SET NOME = ´ + QuotedStr(DeltaDS.FieldByName(´NOME´).AsString) + ´ WHERE CODIGO = ´ + DeltaDS.FieldByName(´CODIGO´).AsString);
      SQLConnect.ExecuteDirect(´UPDATE FILIAL SET NOME = ´ + QuotedStr(DeltaDS.FieldByName(´NOME´).AsString) + ´ WHERE CODIGO = ´ + DeltaDS.FieldByName(´CODIGO´).AsString);
    end;
  end; //case
  //Diz ao DatasetProvider que já foi aplicada a cache
  Applied:= True;
end;


Com o Showmessage descobri que o comando esta sendo enviado assim:
[i:9af8697e7f]UPDATE FILIAL SET NOME = ´TESTE 1´ WHERE CODIGO =[/i:9af8697e7f]

Ou seja, dá o erro porque esta faltando a informação do DeltaDS.FieldByName(´CODIGO´).AsString.

Na exclusão fiz o teste e ele me retorna certinho:
[i:9af8697e7f]DELETE FROM FILIAL WHERE CODIGO = 1[/i:9af8697e7f]

Pergunto: Porque não tenho o campo CODIGO no Delta ? Ou porque esta vindo vazio ?

Obrigado,

Marcello


Marcello

Marcello

Curtidas 0

Respostas

Night_man

Night_man

26/07/2006

jah passei por isso..

o valor do campo quando esta no DeltaDS eh <>.

assim, se for uma insercao esta em NewValue
DeltaDS.FieldByName(´CODIGO´).NewValue,

numa edicao do campo pode ser em dois lugar
o novo valor esta em NewValue
DeltaDS.FieldByName(´CODIGO´).NewValue
e o valor anterior em
DeltaDS.FieldByName(´CODIGO´).OldValue

como codigo nao foi alterado utilize
DeltaDS.FieldByName(´CODIGO´).OldValue

parece estranho a primeira vista mas depois o cara entende....


GOSTEI 0
Marcello

Marcello

26/07/2006

Cara, é isso aí, da certinho.

Tem outro jeito que um amigo me passou também: usar ao invés do DeltaDs o SourceDs.

Obrigado!

Marcello.


GOSTEI 0
Night_man

Night_man

26/07/2006

assim o SorceDS eh todo o dataset que originou a alteracao, o DeltaDS eh um dataset somente com o registro que esta sendo alterado/excluido/inserido


GOSTEI 0
Marcello

Marcello

26/07/2006

:cry: O problema agora é outro: Tenho uma tabela com uns 10 campos - a exclusão e a inserção estão OK, mas a alteração ta pegando, pois como saber dos 10 campos qual foi alterado para criar a SQL de Update ?

Para o exemplo que citei anteriormente, tinha somente 2 campos, mas neste eu não estou sabendo como fazer ?

Obrigado,

Marcello.


GOSTEI 0
Night_man

Night_man

26/07/2006

o update kind te diz qual registro esta sendo alterado (ukmodify), excluido (ukdelete). inserido (ukinsert)


GOSTEI 0
Marcello

Marcello

26/07/2006

OK. A minha dúvida é qual o campo(s) do registro foi alterado ? Por exemplo, suponha que eu tenha os seguintes campos em um registro:
CODIGO, NOME, PRECO
e quero alterar apenas o preco, ou apenas o nome, como eu monto a rotina dentro do ukmodify ?
Se eu alterar o PRECO, o delta não traz nada para o NOME e vice-versa, então como fazer ?


GOSTEI 0
Night_man

Night_man

26/07/2006

eh oq eu de disse antes o negocio dos newvalue e oldvalue

quando o registro eh alterado ele fica com valor nos dois.

valos dizer que tenha dois campos CODIGO e DESCRICAO
CODIGO = 12 e DESCRICAO = ´Teste´

depois da alteracao ficou
CODIGO = 12 e DESCRICAO = ´testando´

quando chegar no update record vai estar assim

FieldByName(´CODIGO´).NewValue = unassigned
FieldByName(´CODIGO´).OldValue = 12

FieldByName(DESCRICAO´).NewValue = ´testando´
FieldByName(DESCRICAO´).OldValue = ´Teste´

ou seja se NewValue <> unassigned eh pq aquele campo fo alterado


GOSTEI 0
Marcello

Marcello

26/07/2006

Então, para o caso que eu citei - COD_PROD, NOME_PROD E PRECO_VEND, ficaria assim ?

    ukModify:
    begin
      If DeltaDS.FieldByName(´NOME_PROD´).NewValue <> Unassigned then
        SQLConnect.ExecuteDirect(´UPDATE PRODUTOS SET NOME_PROD = ´ + QuotedStr(DeltaDS.FieldByName(´NOME_PROD´).AsString)+ ´ WHERE COD_PROD = ´ + SourceDS.FieldByName(´COD_PROD´).AsString);
      If DeltaDS.FieldByName(´PRECO_VEND´).NewValue <> Unassigned then
        SQLConnect.ExecuteDirect(´UPDATE PRODUTOS SET PRECO_VEND = ´ + DeltaDS.FieldByName(´PRECO_VEND´).AsString+ ´ WHERE COD_PROD = ´ + SourceDS.FieldByName(´COD_PROD´).AsString);
    end;


Ou seja, eu teria que testar campo a campo para ver se teve alteração e mandar o comando ?


GOSTEI 0
POSTAR