Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Перехват ошибок IB [D7, IB6.x]


REA ©   (2004-09-02 15:55:00) 

Вопрос наверно очень старый, но в FAQ не нашел: как мне перехватить сообщение IB о нарушении ключа (Key violation)?
Где взять коды ошибок? Как сделать универсальный перехват для разных версий IB и Firebird?


HSolo   (2004-09-06 11:41:00) [1]

>пользовательские EXCEPTION'ы генерирует, видимо
Именно так


jack128   (2004-09-06 10:32:00) [2]

REA   (06.09.04 10:27) [9]
А это как?

пользовательские EXCEPTION'ы генерирует, видимо..


REA   (2004-09-06 10:27:00) [3]

>чтобы не отправлять на сервер заведомую галиматью

Можно перед вставкой наверно проверять, есть ли уже такое ключевое поле и т.п., но тогда надо знать список всех ошибок, которые вероятнее всего могут возникнуть на сервере.

>Плюс еще сервер проверяет, что ему прислали, и если что не так - сообщает об этом по-русски :)

А это как?


HSolo   (2004-09-03 11:31:00) [4]

Это сложнее. Придется, наверное, анализировать сообщение от сервера, вытаскивать из него некие ключевые слова (напр., имена полей) и подставлять вместо них термины, понятные пользователю (скажем, брать в базе описания полей, или сделать свой словарь...)
Просто у меня вышеописанное - вторая линия обороны :) Первая - это экранные формы ввода/редактирования. Там DB-контролов вообще нет, и там делается куча проверок, чтобы не отправлять на сервер заведомую галиматью. Плюс еще сервер проверяет, что ему прислали, и если что не так - сообщает об этом по-русски :) До сих пор мне этого хватало (может, просто везло?)


REA   (2004-09-03 10:19:00) [5]

Спасибо, но тут еще преследуется и другая цель. Просто перевести сообщения на русский язык можно и заменой msg файла, а вот сделать, чтобы они стали понятны пользователю надо потрудиться - нужно выдавать описания полей, а не их названия и т.п.
Как бы это сделать?


HSolo   (2004-09-02 17:43:00) [6]

Создание объекта:
RusMessages := TFIBRusMessages.Create(ExtractFilePath(ParamStr(0))+'fib_rus.txt');
RusMessages.ShowOrigMessage := true;
RusMessages.MyAppHandle := Application.Handle;

fib_rus.txt - файл с кодами ошибок и их переводом, вот кусок:

14=Не указана база данных. Обратитесь к системному администратору
15=База данных недоступна. Обратитесь к системному администратору
-551=Не хватает прав для выполнения операции
-902=Не удалось подключиться к базе данных. Возможно, ошибка в пароле или имени пользователя. Обратитесь к системному администратору


HSolo   (2004-09-02 17:38:00) [7]

Пожалуйста, только у меня все под FIBPlus заточено. Схема такая:
...
Application.OnException := MyAppException;
...
procedure TDM.MyAppException(Sender: TObject; E: Exception);
begin
RusMessages.ShowException(E);
end;

А RusMessages - это экземпляр моего класса-переводчика сообщений:

unit IBRusFIB;

interface

uses Windows, SysUtils, Classes, DB, FIB;

type
TFIBRusMessages = class(TStringList)
 private
       fShowOrigMessage: boolean;
       fAppHandle: HWND;
       function GetRussianMessage(aSQLCode: integer): string;
         //служебная: достать текст ошибки по SQL code и IB Error code
         //если не нашла - вернет sUnknownError
       procedure TranslateDBException(var E: EDatabaseError);
         //Если распознала исключение E, то переводит
         //сообщение E.message на русский (с сохранением текста оригинала)
 public
       constructor Create(aFileName: string);        
       procedure ShowException(var E: Exception);
       //Пытается перевести E.message на русский, после чего выводит E.message
       property ShowOrigMessage: boolean read fShowOrigMessage write fShowOrigMessage;
       property MyAppHandle: HWND read fAppHandle write fAppHandle;
end;

implementation

constructor TFIBRusMessages.Create(aFileName: string);
begin
inherited Create;
fShowOrigMessage := true;
try
  LoadFromFile(aFileName);
  except
  MessageBox(0, PChar('Файл '+aFileName+' не найден'), PChar('Ошибка'), MB_OK or MB_ICONERROR);
  end;
end;

function TFIBRusMessages.GetRussianMessage(aSQLCode: integer): string;
const
 sUnknownError = 'Неизвестная ошибка, обратитесь к программисту';
var s: string;
begin
s := IntToStr(aSQLCode); // + '+' + IntToStr(aIBErrorCode);
Result := Values[s];
if Result = ''
  then Result := sUnknownError;
end;

procedure TFIBRusMessages.TranslateDBException(var E: EDatabaseError);
const
 cServer = chr(13)+chr(10)+chr(13)+chr(10)+'Оригинал сообщения от сервера:'+chr(13)+chr(10)+'%s'+chr(13)+chr(10)+'SQL code: %d';
var s: string;
   ts: TStringList;
begin
 if (E is EFIBError) or (E is EFIBInterBaseError) or (E is EFIBClientError)
 then
 with EFIBError(E) do
 begin
 //особый случай для пользовательских исключений
 if SQLCode = -836
    then begin
         s := message;
         ts := TStringList.Create;
         try
            ts.Text := message;
            s := ts.Strings[ts.count-1];
         finally
                ts.Free;
         end;
         end
    else s := GetRussianMessage(SQLCode);
 if fShowOrigMessage
    then s := s + cServer;
 Message:=Format(s,[Message, SQLCode]);
 end;
end;

procedure TFIBRusMessages.ShowException(var E: Exception);
begin
if E is EDatabaseError
  then TranslateDBException(EDatabaseError(E));
MessageBox(fAppHandle, PChar(E.message), PChar('Внимание!'), MB_OK or MB_ICONWARNING);
end;

end.


REA   (2004-09-02 17:05:00) [8]

>у меня все ловится в Application.OnException

ну покажи плиз как ловишь то (там особой разницы нет на чем ловить) - может пригодится.


HSolo   (2004-09-02 16:53:00) [9]

Так "единообразная обработка для многих таблиц" как раз хорошо ложится на Application.OnException. Впрочем, хозяин - барин :)
Примера для OnPostError нету, у меня все ловится в Application.OnException


REA   (2004-09-02 16:37:00) [10]

>try - except - end
>Application.OnException

Не самый лучший подход на мой взгляд, хотя возможно другой не подойдет.
Логичнее бы перехватить OnPostError например, но
желательно сделать единообразную обработку для многих таблиц.
Вместо указания названий таблиц и полей нужно вывести "Значение поля 'Некое поле или комбинация полей по-русски' повторяется".

Примерчика нету? Сам то я сделаю конечно, но готовое проще испльзовать :)


HSolo   (2004-09-02 16:04:00) [11]

>как мне перехватить сообщение IB о нарушении ключа (Key violation)?
Как и любое другое исключение:
try - except - end
Application.OnException

>Где взять коды ошибок
http://ibase.ru/ib6.htm#doc- Language Reference


Наверх

Титульная страница Поиск, карта сайта Написать письмо