![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перехват ошибок 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