В лекции №2 вставляю модуль данных. При попытке заменить name на fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? |
Программное администрирование баз данных InterBase
Данная лекция позволит изучить способы администрирования баз данных программно, из проекта Delphi. Ведь может случиться, что вы будете писать программу и проектировать базу данных "на заказ", для какой-нибудь небольшой фирмы. Такая фирма, как правило, не может позволить себе иметь в штате профессионального программиста и (или) администратора. В подобных фирмах роль администратора берет на себя один из сотрудников, который является более-менее опытным пользователем. Обучить такого пользователя премудростям и тонкостям работы с утилитой IBConsole непросто, еще сложнее научить его пользоваться утилитами командной строки. И здесь нам на помощь приходит набор компонентов с вкладки " InterBase Admin " палитры компонентов, который входит в стандартный состав Delphi. С помощью этих компонентов можно создать простое приложение, которое будет выполнять административные функции с базами данных, и с которым сможет работать любой пользователь.
Разработка программы AdminIB
Итак, наша задача: создать приложение, которое позволит регулярно делать резервную копию базы first.gdb как в ручном, так и в автоматическом режиме. Также приложение, в случае необходимости, должно уметь восстанавливать базу данных из резервной копии, и сохранять лог-файлы о копировании и восстановлении. В случае каких-то проблем, администратор вышлет вам эти логи, по которым вы сможете определить проблему. Также программа должна уметь добавлять новых пользователей, удалять или редактировать старых. Разумеется, пользователя SYSDBA мы удалять не позволим.
Убедимся, что сервер InterBase у нас работает, и загружаем Delphi. Выделим форму, в свойство Name которой впишем fMain, а в свойство Caption - "Администрирование базы данных First.gdb ". Сохраним проект в отдельную папку, модулю дадим имя Main, а проекту в целом - AdminIB. Неплохо было бы сразу установить свойство BorderStyle в bsDialog, чтобы программа не могла менять размеры, а свойство Position - в poDesktopCenter.
Реализация резервного копирования
Переходим на вкладку Win32 Палитры компонентов, находим и устанавливаем на форму компонент PageControl (каждая задача будет на своей вкладке). Переименуем полученный PageControl1 в PC1 для краткости кода, а свойству Align присвоим значение alClient.
Щелкаем по компоненту PC1 правой кнопкой и выбираем команду New Page - создалась новая вкладка. Выделим ее, и в свойстве Name вместо TabSheet1 напишем TSh1, а в свойстве Caption - "Резервное копирование базы данных". Будьте внимательны: очень легко ошибиться, и вместо листа TabSheet выделить весь компонент PageControl.
Примерный вид вкладки смотрите на рисунке:
Вначале установим на лист панель Panel1, свойству Align которого присвоим значение alTop. Очистим свойство Caption. На панель поместим две радиокнопки RadioButton. В свойству Name первой кнопки укажем RB1, у второй - RB2. А в свойстве Caption, соответственно, "Ручное копирование" и "Автоматическое копирование". Свойство Checked компонента RB2 переведем в True.
Ниже поместим простую кнопку Button, которую переименуем в bStartBackup, а в свойстве Caption напишем "Начать копирование". Свойство Enabled переведем в False. Поскольку по умолчанию, программа будет выполнять автоматическое копирование, эта кнопка будет недоступна. Как только мы выделим радиокнопку "Ручное копирование", сразу вернем доступность этой кнопке.
В правой части панели поместите компонент Label. Чтобы компонент мог содержать многострочный текст, свойство AutoSize переведите в False, а свойство WordWrap - в True. В свойстве Caption напишите текст "Время запуска автоматического резервного копирования:", и подгоните размеры, как на рисунке.
Ниже находятся еще два Label с текстом "Часы:" и "Минуты:". Рядом с ними располагаются два компонента SpinEdit с вкладки Samples Палитры компонентов. Первый переименуйте в SE1, второй - в SE2. У первого в параметре MinValue оставьте 0, в параметре MaxValue укажите 23, а в параметре Value поставьте 1 (по умолчанию, автокопирование будет начинаться в час ночи, когда сотрудников на работе нет). У второго SpinEdit параметры такие: MinValue = 0, MaxValue = 59, Value = 0. Вместо этих компонентов можно было бы использовать один MaskEdit с маской "99:99", но, к сожалению, сам компонент не проверяет правильность ввода значений часов и минут, придется делать это самим. Поэтому остановимся на компонентах SpinEdit, которые позволят пользователю вводить только целые числа в заданном диапазоне.
Под панелью установите компонент Memo. Свойство Align установите в alClient, свойство ScrollBars в ssVertical, и не забудьте очистить от текста свойство Lines.
Далее главное: нужно добавить два не визуальных компонента - Timer с вкладки System и IBBackupService с вкладки InterBase Admin. Компоненты не визуальные, их можно расположить на любом месте, первый будет запускать копирование автоматически, когда подойдет указанное время, второй - осуществлять само копирование. У Timer свойство Interval установите 60000, чтобы таймер срабатывал один раз в минуту.
Компонент IBBackupService предназначен для создания резервных копий базы данных InterBase. Этот компонент позволяет делать различные настройки резервного копирования, в зависимости от того, какие параметры в свойстве Options включены.
У IBBackupService свойство Name для краткости переименуйте в IBBS. На этом приготовления вкладки закончены, приступим к кодированию. Все резервные копии должны попадать в одну папку, например, C:\DataBases\Backup. Эта папка физически должна существовать на диске. При этом мы не сможем делать копии с одним и тем же именем, ведь операционная система не позволит создавать файл с таким же именем. Конечно, можно перед очередным копированием удалять старую копию, но это тоже не выход - что, если новая резервная копия будет создана с ошибками, то есть, в базе данных появились нарушения? Можно было бы восстановить ее из старой копии, но для этого ее не нужно удалять! Выход: добавлять к имени файла дату и время его создания, тогда можно делать сколько угодно копий, и у всех будут разные имена.
Для этого в разделе Private модуля главной формы опишем функцию GetName:
private { Private declarations } function GetName():String;
Установите курсор на название функции и нажмите <Ctrl+Shift+C>, чтобы сгенерировать саму функцию. Вот ее код:
{Функция возвращает префикс имени файла в виде yyyymmdd_hhmmss_ } function TfMain.GetName: String; var ye, mo, da : Word; //для даты ho, mi, se, ms : Word; //для времени st : String[2]; //для добавления нуля, например 05 begin DecodeDate(Date, ye, mo, da); //декодируем на составные дату DecodeTime(Time, ho, mi, se, ms); //декодируем время //теперь собираем строку: Result:= IntToStr(ye); //добавили год //получаем и добавляем месяц: st:= IntToStr(mo); if Length(st) = 1 then st:= '0' + st; //если 1 символ, добавим спереди 0 Result := Result + st; //получаем и добавляем день: st:= IntToStr(da); if Length(st) = 1 then st:= '0' + st; Result := Result + st + '_'; //теперь получаем и добавляем час: st:= IntToStr(ho); if Length(st) = 1 then st:= '0' + st; Result := Result + st; //получаем и добавляем минуты: st:= IntToStr(mi); if Length(st) = 1 then st:= '0' + st; Result := Result + st; //получаем и добавляем секунды: st:= IntToStr(se); if Length(st) = 1 then st:= '0' + st; Result := Result + st + '_'; //теперь функция вернет префикс имени файла, например: //20100205_010012_ end;
Здесь мы декодировали на составные части дату и время. Год уже имеет 4 цифры, поэтому его дополнительно обрабатывать не нужно. А вот месяц, день, час, минута или секунда могут состоять из одной цифры. Чтобы не запутаться, делаем проверку:
st:= IntToStr(mo); if Length(st) = 1 then st:= '0' + st; //если 1 символ, добавим спереди 0 Result := Result + st;
В переменную st мы получаем номер месяца. Если этот номер состоит из одной цифры, перед ней добавим '0'. И в конце прибавим результат в переменную Result. Таким же образом мы проверяем и остальные данные. Эта функция гарантирует нам не только уникальность имени файла, но и правильную сортировку файлов по дате. К тому же по имени сразу видно - когда был создан файл.
Теперь сделаем доступной кнопку bStartBackup, если пользователь отметил радиокнопку RB1 (Ручное копирование). Для этого сгенерируем для RB1 событие onClick:
{Щелкнули по "Ручное копирование"} procedure TfMain.RB1Click(Sender: TObject); begin //если отмечено Ручное копирование, делаем //кнопку доступной: if RB1.Checked then bStartBackup.Enabled:= True; end;
Точно также сделаем кнопку недоступной, если щелкнули по RB2 (Автоматическое копирование). Для этого сгенерируем событие onClick для RB2:
{Щелкнули по "Автоматическое копирование"} procedure TfMain.RB2Click(Sender: TObject); begin //если отмечено Автоматическое копирование, делаем //кнопку недоступной: if RB2.Checked then bStartBackup.Enabled:= False; end;