Управление версиями базы данных в установленных приложениях с помощью Delphi

Мы все еще используем UML. Как другие здесь, я нахожу, что они значительно помогают в коммуникации. Для людей намного легче связаться, когда у них есть визуальные средства (введите популярность PowerPoint). Это особенно верно в начальных фазах проекта, где сценарии как объясненный firebird84 происходят много. Кропотливая сторона к UML является содержанием схем однажды разработчики на кодировании запуска проекта.

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

8
задан Larry Lustig 26 November 2009 в 15:52
поделиться

4 ответа

У меня есть запись в блоге о том, как управление версиями базы данных dbisam и сервер sql .

Важные части:

Поскольку dbisam не поддерживает представления, номер версии сохраняется (вместе с кучей другой информации) в ini файл в каталоге базы данных.

У меня есть модуль данных, TdmodCheckDatabase. Это имеет Компонент TdbisamTable для каждой таблицы в базе данных. Компонент таблицы содержит все поля в таблице и обновляется всякий раз, когда таблица изменено.

Чтобы внести изменения в базу данных, был использован следующий процесс:

  1. Увеличить номер версии в приложении
  2. Внести и протестировать изменения в БД.
  3. Обновить затронутые таблицы в TdmodCheckDatabase
  4. При необходимости (редко) добавить дополнительные запросы на обновление в TdmodCheckDatabase. Например, чтобы установить значения новых полей, или добавить новые строки данных.
  5. Создайте единичный скрипт CreateDatabase, используя предоставленную базу данных. tools.
  6. Обновить модульные тесты для соответствия новой базе данных

Когда приложение запущено, оно с помощью следующего процесса

  1. . Если база данных не найдена, запустите модуль CreateDatabase, а затем выполните шаг 3
  2. Получить текущий номер версии из ini-файла базы данных
  3. Если он меньше ожидаемого номера версии, тогда Запустите CreateDatabase (для создания любых новых таблиц) Проверьте каждый компонент таблицы в TdmodCheckDatabase Применить любые изменения таблицы запускать любые сценарии обновления вручную
  4. Обновить номер версии в ini-файле базы данных

Пример кода:

class procedure TdmodCheckDatabase.UpgradeDatabase(databasePath: string; currentVersion, newVersion: integer);
var
module: TdmodCheckDatabase;
f: integer;
begin
module:= TdmodCheckDatabase.create(nil);
try
  module.OpenDatabase( databasePath );

  for f:= 0 to module.ComponentCount -1  do
  begin
    if module.Components[f] is TDBISAMTable then
    begin
      try
        // if we need to upgrade table to dbisam 4
        if currentVersion <= DB_VERSION_FOR_DBISAM4 then
          TDBISAMTable(module.Components[f]).UpgradeTable;

        module.UpgradeTable(TDBISAMTable(module.Components[f]));
      except
       // logging and error stuff removed
      end;
    end;
  end;

  for f:= currentVersion + 1 to newVersion do
    module.RunUpgradeScripts(f);

  module.sqlMakeIndexes.ExecSQL; // have to create additional indexes manually
 finally
  module.DBISAMDatabase1.Close;
  module.free;
end;
end;


procedure TdmodCheckDatabase.UpgradeTable(table: TDBISAMTable);
var
 fieldIndex: integer;
 needsRestructure: boolean;
 canonical: TField;
begin
 needsRestructure:= false;

 table.FieldDefs.Update;

 // add any new fields to the FieldDefs
 if table.FieldDefs.Count < table.FieldCount then
 begin
   for fieldIndex := table.FieldDefs.Count to table.Fields.Count -1 do
   begin
     table.FieldDefs.Add(fieldIndex + 1, table.Fields[fieldIndex].FieldName, table.Fields[fieldIndex].DataType, table.Fields[fieldIndex].Size, table.Fields[fieldIndex].Required);
   end;
   needsRestructure:= true;
 end;

 // make sure we have correct size for string fields
 for fieldIndex := 0 to table.FieldDefs.Count -1 do
 begin
   if (table.FieldDefs[fieldIndex].DataType = ftString) then
   begin
     canonical:= table.FindField(table.FieldDefs[fieldIndex].Name);
     if assigned(canonical) and (table.FieldDefs[fieldIndex].Size <> canonical.Size) then
   begin
     // field size has changed
     needsRestructure:= true;
     table.FieldDefs[fieldIndex].Size:= canonical.Size;
   end;
   end;
 end;

 if needsRestructure then
   table.AlterTable(); // upgrades table using the new FieldDef values
end;

procedure TdmodCheckDatabase.RunUpgradeScripts(newVersion: integer);
begin
 case newVersion of
   3: sqlVersion3.ExecSQL;
   9: sqlVersion9.ExecSQL;
   11: begin  // change to DBISAM 4
         sqlVersion11a.ExecSQL;
         sqlVersion11b.ExecSQL;
         sqlVersion11c.ExecSQL;
         sqlVersion11d.ExecSQL;
         sqlVersion11e.ExecSQL;
       end;
   19: sqlVersion19.ExecSQL;
   20: sqlVersion20.ExecSQL;
 end;
end;
2
ответ дан 5 December 2019 в 17:38
поделиться

Здесь похожая история. Мы храним номер версии БД в «системной» таблице и проверяем его при запуске. (Если таблица / поле / значение не существует, значит, мы знаем, что это версия 0, в которой мы забыли добавить этот бит!)

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

Когда приложение определяет, что ему необходимо обновить, оно загружает соответствующий ресурс (-ы) и запускает его / их. Если необходимо обновить несколько версий, он должен запустить каждый сценарий по порядку. Оказывается, это всего лишь несколько строк кода.

Суть в том, что вместо использования инструментов на основе графического интерфейса пользователя для изменения таблиц специальным или «случайным» образом мы фактически сразу пишем DDL. Это значительно упрощает, когда придет время, для создания полного сценария обновления. И структурное различие не требуется.

5
ответ дан 5 December 2019 в 17:38
поделиться

What I do is store a version number in the database, and a version number in the application. Every time I need to change the database structure, I create some code update the structure of the database, and increase the version number in the application. When the application starts, it compares, numbers, and if need be runs some code to update the database structure AND update the database's version number. Thus the database is now up to date with the application. My code is something like

if DBVersion < AppVersion then
begin
  for i := DBVersion+1 to AppVersion do
    UpdateStructure(i);
end
else
  if DBVersion > AppVersion then
    raise EWrongVersion.Create('Wrong application for this database');

UpdateStructure just runs the necessary code something like :

procedure UpdateStructure(const aVersion : Integer);
begin
  case aVersion of
    1 : //some db code
    2 : //some more db code
    ...
    ...
  end;
  UpdateDatabaseVersion(aVersion);
end;  

You can actually use the same code to create the database from scratch

CreateDatabase;
for i := 1 to AppVersion do
  UpdateStructure(i);
1
ответ дан 5 December 2019 в 17:38
поделиться

Я использую ADO для своих баз данных. Я также использую схему номеров версий, но только для проверки работоспособности. У меня есть программа, которую я разработал, которая использует Connection.GetTableNames и Connection.GetFieldNames для выявления любых несоответствий с XML-документом, который описывает "главную" базу данных. Если есть несоответствие, я создаю соответствующий SQL для создания недостающих полей. Я никогда не отбрасываю дополнительные.

У меня есть таблица dbpatch, которая содержит список исправлений, идентифицированных по уникальному имени. Если отсутствуют определенные патчи, они применяются, и соответствующая запись добавляется в таблицу dbpatch. Чаще всего это новые сохраненные процедуры, изменение размера полей или индексы

. Я также поддерживаю min-db-версию, которая также проверяется, поскольку я разрешаю пользователям использовать старую версию клиента,

2
ответ дан 5 December 2019 в 17:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: