Fórum ClientDataSet - Dúvidas Matadoras #278723
25/04/2005
0
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
Curtir tópico
+ 0Posts
25/04/2005
Somar
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
25/04/2005
Yuri_fatec
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
01/05/2005
Yuri_fatec
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
Clique aqui para fazer login e interagir na Comunidade :)