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

рис.1.
Ошибка эта появляется в случае, когда Мемо-поле в базе данных не было записано корректно. Ситуация эта происходит как правило в приложениях, использующих редактирование данных в Мемо-полях на какой-то промежуток времени. На период редактирования Мемо-поля, в файле *.dbf помещается ссылка на временный файл, расположенный где-нибудь в C:\TEMP или C:\windows\TEMP. База данных в это время открыта и «ждет» окончания редактирования Мемо-поля и операции сохранения всей записи, включая записи Мемо-поля в *.dbt файл. После того, как редактирование окончено, запись сохраняется в dbf-файл базы данных, а Мемо-поле записывается в dbt-файл. При этом в Мемо-поле остается ссылка на dbt-файл, где собственно и расположено содержимое Мемо-поля. Различного рода факторы, влияющие на разрыв соединения между файлом базы данных и приложением, его открывшем и производящего редактирование, ведут к тому, что связь между ними обрывается и в Мемо-поле остается ссылка на временный файл, а данные оказываются утерянными и не записанными в файлы dbt и dbf базы данных. После чего, при чтении записи с таким «прошлым», приводит к наблюдению рис.1.
2) Создать копию файла с ошибкой, очистить его полностью. Открыть два файла баз данных – с ошибкой и чистый. Считывать в базе данных с ошибкой по одному значению и заполнять соответствующие им значения в чистой «зеркальной» базе данных. В итоге, все ошибочные ссылки в Мемо-полях будут устранены.
Первый метод, конечно, более
сложный и непредсказуемый, так как в записи может быть несколько Мемо-полей, а
полностью считать запись, если там присутствует ошибка, невозможно.
Второй метод, метод «прогона», на практике оказался более эффективным – все, что могло, то считалось и скопировалось в новую базу данных.
Теперь о реализации второго метода обработки ошибки.
Используя классический прием обработки ошибок в Delphi блоком try..except для реализации метода №2 приходим к следующему коду:
procedure CorrectDataBase;
var
i,fc:integer;
Name1,Name2,Dir1:string;
begin
//указываем расположение и имя базы данных с ошибкой
Table1.DatabaseName:=Dir1;
Table1.TableName:=Name1;
Table1.Open;
//производим копирование базы данных, получаем новую базу данных с именем Name2
QuickCopy(Table1, Name2, true);
//очищаем в копии от всех записей
Table2.TableName:=Name2;
Table2.DatabaseName:=Dir1;
Table2.EmptyTable;
//открываем копию для предстоящей работы
Table2.Open;
//вводим переменную, определяющую количество полей в базе
fc:=0;
//начинаем перебирать базу данных, используя за один проход одно поле
while fc < Table1.FieldCount-1 do
begin
Table2.First;
Table1.First;
try
for
i:=0 to Table1.RecordCount-1 do
begin
if fc=0 then
begin
//добавляем записи при первом проходе
Table2.Append;
//присваиваем значение в чистой базе данных значению в базе с ошибкой
Table2.Fields[fc].Value:=Table1.Fields[fc].Value;
end
else
begin
//при втором проходе только редактируем записи
Table2.Edit;
Table2.Fields[fc].Value:=Table1.Fields[fc].Value;
//сохраняем запись
Table2.Post;
//переходим на одну запись вперед
Table2.Next;
end;
Table1.Next;
end;
//в случае ошибки исполняем следующий код
except
on
E:DBErrorEngine do
begin
if fc=0 then
begin
Table2.Append;
//в поле пишем строку с текстом ошибки
Table2.Fields[fc].Value:='Ошибка:'+#13#10+E.Message;
end
else
begin
Table2.Edit;
Table2.Fields[fc].Value:='Ошибка:'+#13#10+E.Message;
Table2.Post;
end;
Table1.Next;
Table2.Next;
end;
end;
//увеличиваем счетчик полей
fc:=fc+1;
end;
//закрываем базы
Table1.Close;
Table2.Close;
end;
Успехов Вам в неблагодарном деле борьбы с ошибками!
архив статьи в формате Microsoft Word (7 Кб)
Владимир Богдановский, delphi-ex.narod.ru
Последние комментарии