ClientDataSet - Dúvidas Matadoras

Delphi

25/04/2005

Olá pessoal...

São duas dúvidas que não consigo esclarecer de forma alguma.
Já pesquisei em diversos lugares e não encontro a solução, espero que
possam me ajudar!


[b:e6d7e1f618]Tratamento de erros nos eventos OnPostError e OnReconcileError[/b:e6d7e1f618]

Gostaria de ter uma lista de erros que poderiam ocorrer ao
chamar os métodos Post e o ApplyUpdates em seguida.

[b:e6d7e1f618]Obs 1:[/b:e6d7e1f618] Sei que, no caso do tratamento de erros de ApplyUpdates,
eu poderia utilizar o HandleReconcileErros, porém acho que
fica complicado para os usuários terem de decidir o que deverá
acontecer caso haja um erro deste tipo. Como eu mesmo gostaria
de decidir o que deveria ser feito de acordo com cada tipo de erro
(erro de violação de chave primária, estrangeira ou de constraint,
por exemplo).

[b:e6d7e1f618]Obs 2:[/b:e6d7e1f618] Estou aqui com uma lista de erros e seus respectivos SQLCODES.
Porém, acredito que os mesmo não servem para tratar erros de Post,
pois esta operação trabalha diretamente com a memória, não sendo
ligada ao banco de dados... Se não me engano os erros de Post
são do tipo EDBClient, porém procurei feito louco por uma lista de erros
deste tipo e não encontrei nada!


[b:e6d7e1f618]Exibindo a posição do cursor em relação ao conjunto de dados[/b:e6d7e1f618]

Sabe aquela informação clássica que informa a posição do cursor
(´Registro 1 de 10´, por exemplo)? Gostaria de saber qual a melhor forma
de implementar a exibição desta informação. Para tal, aprendí duas formas

[u:e6d7e1f618]Vejam o código que utilizo:[/u:e6d7e1f618]

function TDataModule1.PosicaoCursor(DataSet: TDataSet): String
begin
  case DataSet.State of
    dsBrowse:
    begin
      if DataSet.RecordCount > 0 then
        Result := Rotulo + ´ ´ + IntToStr(DataSet.RecNo) + ´ de ´ + IntToStr(DataSet.RecordCount)
      else
        Result := ´Nenhum registro´;
    end;
    dsEdit: Result := ´Editando registro´;
    dsInsert: Result := ´Inserindo registro´;
  end;
end;


[u:e6d7e1f618]1 - No evento AfterScroll do DataSet[/u:e6d7e1f618]

O que acontece: O evento só disparado quando se navega entre os registros ou quando se insere um registro. Logo, nunca será exibida a mensagem ´Editando registro´.

[u:e6d7e1f618]2 - No evento OnCalcFields, utilizando um campo calculado e exibindo
a informação nele[/u:e6d7e1f618]

O evento é disparado sempre (navegando, inserido ou editando), só que
o dataset aqui se encontra no estado dsCalc, ou seja, nenhuma mensagem é exibida. Modifiquei o código para apenas mostrar a posição do registro mesmo (sem utilizar o case). Quando ele está em modo de inserção, exibe a mensagem ´Registro -1 de 100´. Não queria que isso acontecesse.


[u:e6d7e1f618]Conclusão:[/u:e6d7e1f618]

Agradeço à todos pela atenção e espero poder retribuir em brve com meus humildes
conhecimentos.

[ ]´s


Yuri_fatec

Yuri_fatec

Curtidas 0

Respostas

Somar

Somar

25/04/2005

Se eu ententi , coloque o código para a mensagem editanto , inserindo e etc.
no evento
OnStateChange do DataSource ...
ex:
if DataSource.DataSet.Stat = ´DsEdit´ then
Editando registro;
if DataSource.DataSet.Stat = ´DsInsert´ then
Inseringo registro;

Agora com relação o erro de post, se eu não me engado é do tipo e:edatabaseError
Para saber qual a categoria do erro é só gerar o erro que o delphi ira retornar qual a categoria do erro ..


GOSTEI 0
Yuri_fatec

Yuri_fatec

25/04/2005

Se eu ententi , coloque o código para a mensagem editanto , inserindo e etc. no evento OnStateChange do DataSource ... ex: if DataSource.DataSet.Stat = ´DsEdit´ then Editando registro; if DataSource.DataSet.Stat = ´DsInsert´ then Inseringo registro; Agora com relação o erro de post, se eu não me engado é do tipo e:edatabaseError Para saber qual a categoria do erro é só gerar o erro que o delphi ira retornar qual a categoria do erro ..


Obrigado pela atenção amigo...

A sua primeira dica já me ajudou bastante...

EDataBase é a classe pai da EDbClient. Mas e quanto aos códigos de erro? Alguém tem alguma dica?

[ ]´s


GOSTEI 0
Yuri_fatec

Yuri_fatec

25/04/2005

Olá Pessoal

Desculpem pela demora em escrever este tópico relatando a solução de um dos problema levantados aqui (Tratamento de erros de Post e ApplyUpdates).

Descrobrí pesquisando em artigos da [b:51d8f8ed66]Borland Developer Network[/b:51d8f8ed66], especialmente nos artigos de Carry Jansen (que com certeza é a melhor de todas as fontes de consulta sobre o desenvolvimento de aplicações para bancos de dados com DBExpress + MIDAS, que se você utiliza uma suíte de componentes que não seja do BDE, não poderá manipular erros pelo seu código! Para tal, você precisará fazer um parser para avaliar a propriedade [b:51d8f8ed66]Message [/b:51d8f8ed66] do Erro e poder manipular o erro.

Eu como não estou utilizando esta maldita e arcaica tecnologia, e sim DBExpress + MIDAS, tive que fazer o maldito parser, que avalia as mensagens de erro mais comuns (violação de chave primária, estrangeira, violação de constraint e conflito de atualizações).

Como ja fui muito auxiliado pelos amigos do fórum, decidí postar aqui a solução que desenvolví para tentar ajudá-los tb de alguma forma... Aí vai:


{ Coloquem o código abaixo no local onde estão seus ClientDataSets (geralmente num datamodule, mas se estiverem num form, coloquem nele!) }

// Tipos Enumeração que eu crie para tratar o erro facilmente.
// Eles serão os valores de retorno das funções que criei para
// avaliar as mensagens de erro.

// Constantes enumeradas para erros retornados pelo SGBD firebird
// após chamar o método ApplyUpdates do ClientDataSet

{ colocar em [b]interface[/b]}

type TErrosFBEnum = (
  efbConstraint,
  efbPKUK,
  efbFK,
  efbConflito,
  efbDesconhecido
);

// Constantes enumeradas para erros retornados pelo ClientDataSet,
// após chamar o método Post do ClientDataSet

type TErrosCDSEnum = (
  ecdsViolacaoChave,
  ecdsDesconhecido
);

function DetectarErrosBD(E: EReconcileError): TErrosFBEnum;
function DetectarErrosCDS(E: EDatabaseError): TErrosCDSEnum;

{ colocar na [b]implementation[/b]}

function DetectarErrosBD(E: EReconcileError): TErrosFBEnum;
begin
  if Pos(´validation error´, E.Message) <> 0 then
    Result := efbConstraint
  else if Pos(´violation of FOREIGN KEY´, E.Message) <> 0 then
    Result := efbFK
  else if Pos(´violation of PRIMARY or UNIQUE KEY´, E.Message) <> 0 then
    Result := efbPKUK
  else if Pos(´Record not found or changed by another user´, E.Message) <> 0 then
    Result := efbConflito
  else
    Result := efbDesconhecido;
end;

function DetectarErrosCDS(E: EDatabaseError): TErrosCDSEnum;
begin
  if Pos(´Key violation´, E.Message) <> 0 then
    Result := ecdsViolacaoChave
  else
    Result := ecdsDesconhecido;
end;

// Utilização das funções criadas
// Trecho tirado do meu programa. Este código consta no evento
// OnReconcileError do meu ClientDataSet

procedure TdmGerProfessores.cdsProfessorReconcileError(
  DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind;
  var Action: TReconcileAction);
begin
  case DetectarErrosBD(E) of
    // Erro de restrição
    efbConstraint:
    begin
      MessageDlg(
        ´Erro ao salvar ´ + DataSet.Name + #10131013 +
        ´Valor inválidos ou nulos foram encontrados em campos com restrições.´,
        mtError, [mbOK], 0
      );
      Action := raAbort
    end;
    // Erro de chave primária (PK) ou chave única (UK)
    efbPKUK:
    begin
      MessageDlg(
        ´Erro ao salvar ´ + DataSet.Name + 10131013 +
        ´Campos que não aceitam valores duplicados possuem valores duplicados.´,
        mtError, [mbOK], 0
      );
      Action := raAbort;
    end;
    // Erro de chave estrangeira
    efbFK:
    begin
      MessageDlg(
        ´Erro ao salvar ´ + DataSet.Name + 10131013 +
        ´Valores digitado em campos dependentes não possuem correspondentes válidos.´,
        mtError, [mbOK], 0
      );
      Action := raAbort;
    end;
    // Erro de chave estrangeira
    efbConflito:
    begin
      MessageDlg(
        ´Erro ao salvar ´ + DataSet.Name + 10131013 +
        ´O registro foi modificado ou deletado por outro usuário. Os dados do registro serão recarregados.´,
        mtError, [mbOK], 0
      );
      Action := raRefresh;
    end;
  else
    MessageDlg(
      ´Erro ao salvar ´ + DataSet.Name + 10131013 +
      ´Erro desconhecido!´,
      mtError, [mbOK], 0
    );
  end;
end;

procedure TdmGerProfessores.cdsProfessorPostError(DataSet: TDataSet;
  E: EDatabaseError; var Action: TDataAction);
var
  CodigoProf: Integer;
  Acao: Integer;
begin
  inherited;
  // [b]O TRECHO QUE IMPORTA[/b]
  case DetectarErrosCDS(E) of
    ecdsViolacaoChave:
    begin
      CodigoProf := cdsProfessorPROFESSOR_ID.AsInteger;
      Acao := MessageDlg(
        ´Já existe um professor com o código informado!´ + 10131013 +
        ´Gostaria de ir para ele e conferir? (Os dados digitados do professor serão perdidos)´,
        mtWarning, [mbYes, mbNo], 0
      );
      // Move o cursor para o professor com o código
      // informado, mas que porém já pertence a outro
      // professor
      if Acao = mrYes then
      begin
      cdsProfessor.Cancel;
        cdsProfessor.Locate(´PROFESSOR_ID´, CodigoProf, []);
      end;
    end
  else
    MessageDlg(
      E.Message,
      mtWarning, [mbOk], 0
    );
  end;
Action := daAbort;
end;



Dica final: Quase tudo que vc precisa aprender sobre o assunto discutido se encontra na BDN. Faça um teste! Pesquise no google utilizando a seguinte frase de pesquisa: [color=blue:51d8f8ed66]ClientDataSet site:bdn.borland.com[/color:51d8f8ed66])

Abraços pessoal!


GOSTEI 0
POSTAR