problema clientdataset.delete

Delphi

01/09/2009

pessoal, eu escrevi o seguinte codigo

try
screen.Cursor := crSQLWait;
if Application.MessageBox(´Deseja realmente excluir este registro?´,´Mensagem do Sistema´,MB_ICONQUESTION+mb_yesno)=mryes then
begin
try
dm.ADOConnection.BeginTrans;
DataSource.DataSet.Delete;
(DataSource.DataSet as TClientDataset).ApplyUpdates(0);
dm.ADOConnection.CommitTrans;
except on
exc: exception do
begin
if Application.MessageBox(pchar(EXC.MESSAGE),´Mensagem do Sistema´,mb_iconerror+mb_ok)=mrok then
begin
if dm.ADOConnection.InTransaction then
begin
dm.ADOConnection.RollbackTrans;
end;
end;
end;
end;
end;
finally
screen.Cursor := crDefault;
end;

o sistema exibe a mensagem de erro quando a violação de chave
, mas ocorre a atualização no clientdataset

tento excluir um registro e aparece o erro, qdo dou ok, o registro some do dataset, mas permanece no banco de dados

alguem ja viu isso, como posso corrigir

abraço


Arc

Arc

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

01/09/2009

aparentemente você está tentando excluir um registro que é referenciado em outras tabelas (tipo excluir um mestre que possui detalhes).
se for algo assim, altere as propriedades do provider ou do banco de dados de modo a excluir os registros em cascata.


GOSTEI 0
Arc

Arc

01/09/2009

emerson, eu não posso excluir em cascata

o sistema não pode excluir o registro se tiver referenciando outra tabela


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/09/2009

tente o método CancelUpdates.
try
  if Application.MessageBox(´Deseja realmente excluir este registro?´,´Mensagem do Sistema´,MB_ICONQUESTION+mb_yesno)=mryes then
  begin
    screen.Cursor := crSQLWait;

    try
      dm.ADOConnection.BeginTrans;
      DataSource.DataSet.Delete;
      (DataSource.DataSet as TClientDataset).ApplyUpdates(0);
      dm.ADOConnection.CommitTrans;
    except on
      exc: exception do
      begin
        (DataSource.DataSet as TClientDataset).CancelUpdates;
        if dm.ADOConnection.InTransaction then
          dm.ADOConnection.RollbackTrans;
        Application.MessageBox(pchar(EXC.MESSAGE),´Mensagem do Sistema´,mb_iconerror+mb_ok)=mrok
      end;
    end;
  end;
finally
  screen.Cursor := crDefault;
end;



GOSTEI 0
Arc

Arc

01/09/2009

infelizmente a mesma coisa


GOSTEI 0
Osocram

Osocram

01/09/2009

bom isso pode ser pq a transação é controle q se faz no banco e não no ClientDataSet;
Qdo der um erro vc tem que carregar os dados novamente.

Esse é um erro que ja vi em varios lugares, inclusive eu mesmo ja o fiz muitas vezes.

O ClientDataSet grava tudo em memoria.
As transações não tem nada a ver com o ClientDataSet (diretamente).
Mesmo dando um rollback o clientDataSet continua na mesma.

No seu exemplo mesmo depois do rollBack se vc der um applyUpdate novamente ele vai tentar executar o delete.

Então o Cancel ou CancelUpdate ou até mesmo um Open ou refresh para trazer os dados novamente.


GOSTEI 0
Arc

Arc

01/09/2009

osocram,

eu fiz um tratamento de exceção no evento ReconcileError

coloquei Action:=raCancel; após a mensagem de erro, e o registro reaparece.

ficou um tanto estranho, mas foi a unica solução menos pior que encontrei

estou acostumado a fazer tudo via adoquery, usando inserts, deletes e updates.

ha muito tempo queria mexer um pouco com o clientdataset, mas nunca tive oportunidade. estou me batendo bastante com os detalhes dele, mas é isso ai

vlw


GOSTEI 0
Osocram

Osocram

01/09/2009

é assim mesmo... com o tempo agente vai aprendendo coisas novas

outra dica caso precise, ja que o ClientDataSet em tratamento de exceção silencioso por isso vc precisa usar o reconcilleError

vc pode fazer assim p saber qtos erros deu
erro:integer;

erro := cds.applyUpdates(0);
if erro > 0 then
showmessage(´erro´);


GOSTEI 0
POSTAR