Fórum Traduzir mensagem do Banco clientdataset e firebird #325228
12/07/2006
0
em assunto não é novo . JA fiz uma pesquisa , mas so achei algo parecido em
http://forum.clubedelphi.net/viewtopic.php?t=47844&highlight=chave+primaria+mensagem
so que ele não disse como resolveu ??? :cry: :cry: :cry:
então venho lançar novamente esta questão
Tenho uma chave primária , e no momento que dou um apllyUpdates no Cds me retorna o erro
[b:750819b664]Field ´COMPOSICAO´ must have a value[/b:750819b664]
Gostaria de interceptar esta mensagem de erro retornada pelo Banco de Dados , para transforma-la em uma mensagem mais amigavel
O Problema é que não estou conseguindo interceptar a mensagem que vem do Banco , para trata-la
E Mais estranho que coloquei um codigo no evento [b:750819b664]OnEconcileError[/b:750819b664] , e este evento nesta situação Não é disparado :cry: :cry: :cry:
procedure TDm.CdCompReconcileError(DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction); begin showmessage(´Evento NÃO É DISPARADO...PORQUE ????); end;
Marco Salles
Curtir tópico
+ 0Posts
14/07/2006
Marco Salles
Desde ontem so quatro visitas :evil: :evil: :evil:
E mesmo assim estas quatro visitas acho que forma minhas , vendo e relendo o tópico. :lol: :lol: :lol: :lol:
Gostei + 0
14/07/2006
Macario
Não tenho a resposta para este assunto, mas tenho interesse pelo mesmo.
Você ja tentou tratar o evento usando a variavel [b:cd4b68b69c]UpdateKind[/b:cd4b68b69c]?
E a mensagem?
Gostei + 0
14/07/2006
Marco Salles
a messagem vem do Banco e a principio ela não é propagada pelo ClienteDataset..
o Evento OnReconcileError nen é disparado.... É isto que esta me deixando encucado... Na hora que dou um ApllyUpdated(0) , porque este evento não esta sendo Disparado :?: :?: :?: :?: :?:
Gostei + 0
15/07/2006
Lindomar.des
Sou iniciante ainda nesse tipo de acesso, mas pelo que sei o evento OnReconcileError é disparado qdo ha divergencias entre as informações do registro que vc está vendo com o q está no banco. Tipo: duas pessoas alteram o preço de um mesmo produto, na hora que o ultimo gravar ocorrerá o erro. Para o que vc está tentando fazer recomendaria o evento
OnPostError do clientedataset: exmplo:
procedure TdmMProvider.CDSPostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
begin
if (Pos(´Field value required´, e.Message) > 0) or (Pos(´must have a value´,
e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, verifique os campos em vermelho. São de preenchimento obrigatório!´),
´Validação´, mb_ok + MB_ICONERROR);
Action := daAbort;
end;
end;
ainda para fazer outras validações vc pode usar o evento OnUpdateError
do DataSetProvider. exemplo:
procedure TdmMProvider.DSPUpdateError(Sender: TObject;
DataSet: TCustomClientDataSet; E: EUpdateError; UpdateKind: TUpdateKind;
var Response: TResolverResponse);
begin
//registro já cadastrado - Duplicar chave primária
if (UpdateKind = ukInsert) and (Pos(´PRIMARY or UNIQUE KEY´, e.Message) > 0)
then
MessageBox(Application.Handle, (PChar(e.Message + #13 + 13 +
dmDBEXMaster.sUsuario + ´, você está tentando gravar uma informação que´
+ ´ já existe no banco de dados!´)), ´Validação´, mb_ok +
MB_ICONERROR)
else if (UpdateKind = ukInsert) and (Pos(´insert/write´, e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, você não possui permissão para incluir neste módulo!´), ´Validação´,
mb_ok + MB_ICONERROR);
(DataSet as TClientDataSet).CancelUpdates;
end
else if (UpdateKind = ukDelete) and (Pos(´delete/write´, e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, você não possui permissão para excluir neste módulo!´), ´Validação´,
mb_ok + MB_ICONERROR);
(DataSet as TClientDataSet).CancelUpdates;
end
else if (UpdateKind = ukDelete) and (Pos(´empty´, e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, o arquivo está vazio. Impossível exluir!´), ´Validação´,
mb_ok + MB_ICONERROR);
(DataSet as TClientDataSet).CancelUpdates;
end
//integridade referencial
else if (UpdateKind = ukDelete) and (Pos(´FOREIGN´, e.Message) > 0) or
(Pos(´Chave Estrangeira´, e.Message) > 0) then
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, houve violação da integridade referencial!´ + #13 + 13 +
´Você está tentando excluir um registro que está fazendo referência´
+ #13 + ´a outra tabela do banco de dados. A operação será cancelada!´),
´Integridade´, mb_ok + MB_ICONERROR)
//privilégios
else if (UpdateKind = ukModify) and (Pos(´update/write´, e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, você não possui permissão para alterar neste módulo!´), ´Validação´,
mb_ok + MB_ICONERROR);
(DataSet as TClientDataSet).CancelUpdates;
end
else if (Pos(´Filed value required´, e.Message) > 0) then
begin
MessageBox(Application.Handle, PChar(dmDBEXMaster.sUsuario +
´, verifique os campos em vermelho, são de preenchimento obrigatório!´),
´Validação´, mb_ok + MB_ICONERROR);
(DataSet as TClientDataSet).CancelUpdates;
end;
Response := rrAbort;
end;
esse são alguns trechos do cod. que uso.
Gostei + 0
15/07/2006
Marco Salles
nesse tipo de erro , usando [b:053fbc84ae]Cds , firibirid e DbExpress [/b:053fbc84ae], ate agora em nenhum desses eventos :arrow: :arrow: consegui evitar a mensagem que [b:053fbc84ae]vem do Banco[/b:053fbc84ae]
:idea: :idea:
[b:053fbc84ae]Não apresenta nada no OnReconcileError nada no .CDSPostError nada no .DSPUpdateError...Estes eventos simplesmente não são disparados[/b:053fbc84ae]
[URL=http://imageshack.us][img:053fbc84ae]http://img204.imageshack.us/img204/315/imagemlindomar1hj7.png[/img:053fbc84ae][/URL]
:lol: :lol: :lol:
Mas isto não é o que a gente quer é o que a gente precisa
[b:053fbc84ae]Lendo vários tópicos , estou inclinado a tomar duas decisoes.[/b:053fbc84ae]
Mas vou tentar com a primeira , qua deixarei aqui a idéia para que alguem possa contribuir
:idea: :idea: :idea: :idea:
[b:053fbc84ae]é a criação de uma exceção no Proprio Banco..[/b:053fbc84ae]
Isto é fácil de fazer usando O [b:053fbc84ae]IBExpert[/b:053fbc84ae]
:cry: :cry: :cry: :cry:
[b:053fbc84ae][color=darkred:053fbc84ae]o que eu não estou conseguindo é usando uma trigger , disparar esta exceção[/color:053fbc84ae][/b:053fbc84ae]
[b:053fbc84ae]A idéia seria esta .. Se ja existe um Produto com esta descrição , entaõ levanto a exceção <que fora criada por mim>[/b:053fbc84ae]
:cry: :cry: :cry:
[b:053fbc84ae]não estou conseguindo a sintase para esta trigger[/b:053fbc84ae]
Feito isto a mensagem que sera apresentada para o usuário é a mensagem definida e ela com certeza pode ser tratada no evento OnReconcileError
[b:053fbc84ae]Mas ta faltando esta Trigger...[/b:053fbc84ae] :cry: :cry: :cry:
Gostei + 0
19/07/2006
Marco Salles
[b:c6c87eab7e]Ainda sem solução . No Aguardo e acreditando na possibilidade de solução[/b:c6c87eab7e]
Gostei + 0
20/07/2006
Marco Salles
AS begin if (exists(select 1 from composicao where DESCRICAO=new.descricao)) then exception ERROR_CHAVE_DUPLICADA_COMPOSICA ; else begin insert into materia_prima (descricao,Saldo,data,Valor,Unidades) values (new.descricao,0,CURRENT_DATE,0,new.unidade); end end
A ideia é gerar uma exceção , para que possa trata-la no evento OnReconcileError do ClientDataSet. É claro que por se tratar de uma chave primária , por se so o banco lança uma exceção , na hora que se tenta lançar dois produtos com a mesma descrição.. Mas a mensagem que o banco lança não é muito amigável
Porem , não sei porque , não consigo captutar este Erro para que trasmita uma mensagem mais amigável
Ainda não desisti...
Gostei + 0
20/07/2006
Emrinfo
Marcos Salles, eu faco o seguinte no evento do OnReconcileError do ClientDataSet, eu testo como no exemplo abaixo:
Msg:= ´Descricao nao disponivel.´;
if (Pos(´violation of PRIMARY or UNIQUE KEY´, E.Message) > 0) or
(Pos(´attempt to store duplicate value´, E.Message) > 0) then
Begin
Msg:= ´A tentativa de insercao/edicao iria resultar em duplicidade ´ +
´de registros nesta tabela.´;
End;
if (Pos(´violation of FOREIGN KEY´, E.Message) > 0) then
Begin
Msg:= ´A tentativa de atualizacao iria causar falhas de relacionamento, ´ +
´por existirem dependentes entre as tabelas envolvidas.´;
End;
ShowMessage(E.Message + #13 + ´Descricao do erro: ´ + 13 + Msg);
Espero ter ajudado.
Evaldo.
Gostei + 0
20/07/2006
Marco Salles
[b:6e728fab2a]O problema é que nesta situação , o evento onReconcileError não é disparado.. Então nada que tiver escrito nele , é executado...[/b:6e728fab2a]
Gostei + 0
24/07/2006
Cabelo
segue abaixo :
Primeiro a Function Grava
Function F_Grava(l_Banco : TSQLConnection; l_sql:string) : boolean; overload; var v_desc : TTransactionDesc; v_query : TSQLQuery; v_provider : TDataSetProvider; v_client : TClientDataSet; begin v_query := TSQLQuery.Create(nil); v_query.SQLConnection := l_Banco; v_provider := TDataSetProvider.Create(nil); v_provider.DataSet := v_query; v_provider.Name := ´PROVIDER_GRAVA´; v_client := TClientDataSet.Create(nil); v_client.ProviderName := ´PROVIDER_GRAVA´; try begin v_desc.TransactionID := 1; v_desc.IsolationLevel := xilREADCOMMITTED; l_Banco.StartTransaction(v_desc); try begin result := F_query(v_query, v_client, L_sql, ´E´); l_Banco.Commit(v_desc); v_client.Free; v_provider.Free; v_query.Free; end; except on E:Exception do begin l_Banco.Rollback(v_desc); result := false; v_client.Free; v_provider.Free; v_query.Free; P_Message_Error(E.Message); end; end; end; except result := false; v_client.Free; v_provider.Free; v_query.Free; end; end;
a Função F_query
function F_Query(l_Query:TSQLQuery; l_Client : TClientDataSet; l_comando:string; l_Tipo:string) : Boolean; var v_disable : Boolean; begin v_disable := l_query.ControlsDisabled; Result := False; if not v_disable then l_Query.DisableControls; Try if l_Query.Active then l_Query.Close; if l_Client.Active then l_Client.Close; l_Query.Sql.Clear; l_Query.Sql.Add(l_comando); if l_Tipo = ´E´ then begin l_Query.ExecSQL; if l_Query.RowsAffected > 0 then Result := True else Result := False; end else if l_Tipo = ´O´ then begin l_Query.Open; l_Client.Open; Result := (not l_Client.isEmpty); end; Finally If not v_disable then l_Query.EnableControls; End; end;
a procedure Message_Error
procedure P_Message_Error(l_desc : string); begin if Pos(´string truncation´, l_desc) > 0 then begin MessageDlg(´Um dos campos que vc está tentando inserir é muito grande, ´+ ´ou contém caracteres especiais não suportados pelo Banco de Dados ´+ ´usado neste sistema. Contate seu supervisor!´, mtError, [mbOk], 0); end; if Pos(´VIOLATION´, l_desc) > 0 then begin MessageDlg(´Registro duplicado. Favor corrigir!´, mtError, [mbOk], 0); end; end;
Essa Função : F_grava, deve ser usada sempre que desejar startar uma transaction no Banco..
a procedure P_Message_Error, pode ser acrescentada as mensagens que vem do banco.. desta forma funciiona perfeitamente..
espero ter ajudado..
Gostei + 0
24/07/2006
Minuto
criei uma procedure:
procedure trataerro(emsg:string); var msg:string ; begin //violação de chave primaria ou campo unico if (Pos(´violation of PRIMARY or UNIQUE KEY´, emsg) > 0) or (Pos(´attempt to store duplicate value´, emsg) > 0) then begin msg:= ´A tentativa de inserção/edição iria resultar em duplicidade ´ + ´de registros nesta tabela.´; end; //violação de relacionamento if Pos(´violation of FOREIGN KEY´, emsg) > 0 then begin Msg:= ´A tentativa de atualização iria causar falhas de relacionamento, ´+ ´por existirem dependencias entre as tabelas envolvidas.´; end; //campo Obrigatório! if Pos(´must have a value´, emsg) > 0 then Msg:= ´Este campo não pode ser vazio ou seu valor é inválido!´; ShowMessage(emsg + #13 + ´Descrição do Erro: ´ + 13 + Msg); end;
e depois uso o evento onposterror do CDS:
procedure TDM.cdscandidatoPostError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction); begin trataerro(e.Message); action := daAbort; end;
Gostei + 0
24/07/2006
Marco Salles
Muito obrigado.
Gostei + 0
24/07/2006
Cabelo
no meu exemplo... não importa qual é o componente que vc está usando... pois a gravação será feita através de um SQL...
embora deixe a aplicação um pouco mais complexa, sendo que vc precise tratar todas as rotinas manualmente, fica perfeitamente portável para qualquer banco... independente dos componentes que vc usa...
estas rotina interceptam as excessões do sistema...
INDEPENDENTEMENTE do componente usado..
um abraço..
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)