Недоработка в VCL.
Сейчас вышел из ситуации так: в TForm.OnClose, т.е. пока ещё все компоненты формы живы, делаю CloseDatabases(Self).
При обращении к memo-полю из BDE возникает ошибка 'Memo too large'. Как лечить?
Nomadic отвечает:
В BDE есть крутая ошибка, достаточно известная всем, кроме Borland'a. Поскольку они ее еще с 1й Delphi не исправили. Этот баг проявляется как Access Violation в программе при обращении к таблице IB, которая содержит более одного поля типа VARCHAR (или CHAR) размером>255. Причем, первое поле меньшего, а второе большего размера. Если поменять местами поля или сделать их одного размера, то все нормально.
Эффект имеет место только с IB, вроде.
Нарушение уникальности записи
Delphi 1
try
tMyTable.Post;
except
on E : EDBEngineError do if E.Message = 'Key violation' then begin
MessageDlgC('Дублирование записи не допускается.' mtError, [mbOk], 0);
// Я не уверен в том, что это нужно делать:
tMyTable.Cancel;
end
else Raise;
end;
Хорошим примером может служить проект DBERRORS.DPR, расположенный в каталоге Delphi 2 Demos. Выглядит это примерно так:
Создайте функцию типа этой:
function DBError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction);
const eKeyViol = 9729;
var iDBIError: Integer;
begin
if (E is EDBEngineError) then begin
iDBIError := (E as EDBEngineError).Errors[0].Errorcode;
case iDBIError of
eKeyViol:
begin
MessageDlg('Нарушение уникальности записи ', mtWarning, [mbOK], 0);
Abort;
end;
end;
Затем для каждой таблицы вашего приложения создайте следующий обработчик события:
procedure TMainForm.Table1EditError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction);
begin
DBError(Table1, E, Action);
end;
Таким образом вы можете перехватить множество ошибок. Смотрите примеры от Borland, там много чего есть полезного.
При выполнении некоторых живых запросов, возвращающих единственную запись, BDE ругается 'multiple records found, but only one was expected'. Как лечить?
Nomadic отвечает:
Запросы вида SELECT c, b, a, q FROM T WHERE b = :b, где ключ c, но BDE посчитала ключом a. Интересный запрос, да? Такое впечатление, что, поскольку ключом в исходной таблице являлась третья колонка, то Дельфы посчитали ключом третью колонку.
Перестановкой SELECT a, b, c, q… все исправилось. Я решил теперь использовать в таких (live) запросах только SELECT *.
Как поймать свой RAISEERROR в Delphi?
Nomadic отвечает:
procedure TFDMUtils.GeneralError( DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction);
var
i: Word;
ExtInfo : String;
begin
ExtInfo := '';
if (E is EDBEngineError) then begin
if (EDBEngineError(E).Errors[0].NativeError = 0) then begin // Local Error
if EDBEngineError(E).Errors[0].Errorcode = 9732 then
ExtInfo := DataSet.FieldByName(trim(copy(E.Message, 29, 20))).DisplayLabel;
.......................................
end
else begin // Remote SQL Server error
ExtInfo := ExtractFieldLabels(DataSet, E.Message);
case EDBEngineError( E ).Errors[0].NativeError of
233, 515:
Alert('Ошибка', 'Hе все поля заполнены ! ' + ExtInfo);
547:
if (StrPos(PChar(E.Message), PChar('DELETE')) <> nil) then
Alert('Ошибка пpи удалении', 'Имеются подчиненные записи, удаление (изменение) невозможно! ' + ExtInfo)
else if (StrPos(PChar(E.Message), PChar('INSERT')) <> nil) then