8

私は多くの Delphi アプリケーションに取り組んでおり、新しいバージョンがリリースされたときや、ユーザーが追加モジュールをインストールすることを選択したときに、現場で独自のデータベース構造をアップグレードする必要があります。アプリケーションはさまざまな組み込みデータベースを使用しています (現在 DBISAM と Jet ですが、これは変更される可能性があります)。

過去に、各テーブルに格納できるユーザー バージョン番号を使用して、DBISAM でこれを実行しました。追加の空のデータベース ファイル セットを出荷し、起動時に FieldDefs を使用して各テーブルのバージョン番号を比較し、必要に応じてインストールされたテーブルを更新しました。これはうまくいきましたが、データベースの予備のコピーを出荷しなければならないのは不器用であることがわかりました。新しいバージョンの DBISAM ではテーブルの再構築方法が変更されているため、とにかくこれを書き直す必要があります。

これを実装する方法は 2 つあります。データベースにバージョン番号を格納する方法と、DDL スクリプトを使用して古いバージョンから新しいバージョンに移行する方法と、データベース構造の参照バージョンをアプリケーション内に格納して、開始時にデータベースへの参照を比較する方法です。アップし、アプリケーションで DDL コマンドを生成してデータベースをアップグレードします。

おそらく両方の部分を実装する必要があると思います。アプリケーションが起動するたびに (遅すぎる) データベースを参照構造と比較したくないので、ユーザーが古い構造を使用しているかどうかを検出するために、データベース構造のバージョン番号が必要です。ただし、データベースが過去に部分的に更新された可能性がある場合、またはユーザー自身がデータベース構造を変更した可能性がある場合、事前に作成されたスクリプトを使用して構造をアップグレードできるかどうかはわかりません。実際の更新については diff を参照してください。

質問を調査すると、データベースのバージョン管理ツールがいくつか見つかりましたが、それらはすべて SQL Server を対象としており、実際のアプリケーションの外部に実装されているようです。アプリケーションに緊密に統合され、さまざまなデータベース要件に適応できるプロセスを探しています (さまざまな DDL の違いを処理するために、アダプター、カスタム子孫クラス、またはイベント コードを作成する必要があることはわかっています)。データベース、それは私を悩ませません)。

これを行う、またはそれを失敗させる既製のものを知っている人はいますか?

  1. ジェネリック リレーショナル データベース構造の参照バージョンをアプリケーション内に格納する最良の方法。

  2. 参照を実際のデータベースと比較する最良の方法。

  3. データベースを更新するための DDL を生成する最良の方法。

4

4 に答える 4

5

似たような話はこちら。DB のバージョン番号を「システム」テーブルに保存し、起動時に確認します。(テーブル/フィールド/値が存在しない場合は、そのビットを追加するのを忘れたバージョン 0 であることがわかります!)

開発中にデータベースをアップグレードする必要がある場合は、DDL スクリプトを作成して作業を行い、問題なく動作することを確認したら、テキスト リソースとしてアプリに追加します。

アプリは、アップグレードが必要であると判断すると、適切なリソースをロードして実行します。複数のバージョンをアップグレードする必要がある場合は、各スクリプトを順番に実行する必要があります。最終的には、ほんの数行のコードであることがわかります。

主なポイントは、GUI ベースのツールを使用してその場限りまたは「ランダム」な方法でテーブルを変更する代わりに、実際に DDL をすぐに作成することです。これにより、必要なときに完全なアップグレード スクリプトを作成することがはるかに簡単になります。また、構造の差分は必要ありません。

于 2009-11-27T09:34:23.240 に答える
2

データベースに ADO を使用しています。バージョン番号スキームも使用しますが、サニティ チェックとしてのみ使用します。Connection.GetTableNames と Connection.GetFieldNames を使用して、「マスター」データベースを記述する XML ドキュメントとの不一致を識別するプログラムを開発しました。不一致がある場合は、不足しているフィールドを作成するための適切な SQL を作成します。追加のものをドロップすることはありません。

次に、一意の名前で識別されるパッチのリストを含む dbpatch テーブルを作成します。特定のパッチが欠落している場合は、それらが適用され、適切なレコードが dbpatch テーブルに追加されます。ほとんどの場合、これは新しいストアド プロシージャ、フィールドのサイズ変更、またはインデックスです。

また、min-db-version も維持しています。ユーザーが古いバージョンのクライアントを使用できるようにするため、これもチェックされます。min-db-version >= min-db-version および <= cur-db のバージョンのみを使用できるようにします。 -バージョン。

于 2009-11-30T17:29:08.940 に答える
2

dbisam データベースのバージョン管理sql serverを行う方法についてのブログ投稿がここにあります。

重要な部分は次のとおりです。

dbisam はビューをサポートしていないため、バージョン番号は (他の情報と共に) データベース ディレクトリの ini ファイルに保存されます。

データモジュール TdmodCheckDatabase があります。これには、データベース内のすべてのテーブルの TdbisamTable コンポーネントがあります。テーブル コンポーネントにはテーブル内のすべてのフィールドが含まれ、テーブルが変更されるたびに更新されます。

データベースを変更するために、次のプロセスが使用されました。

  1. アプリケーションのバージョン番号を増やします
  2. DB の変更を行い、テストします。
  3. TdmodCheckDatabase で影響を受けるテーブルを更新します
  4. 必要に応じて (ほとんどありませんが)、さらにアップグレード クエリを TdmodCheckDatabase に追加します。たとえば、新しいフィールドの値を設定したり、新しいデータ行を追加したりします。
  5. 提供されたデータベース ツールを使用して、CreateDatabase ユニット スクリプトを生成します。
  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;
于 2009-11-27T00:10:34.347 に答える
1

私がしているのは、バージョン番号をデータベースに保存し、バージョン番号をアプリケーションに保存することです。データベース構造を変更する必要があるたびに、データベースの構造を更新するコードをいくつか作成し、アプリケーションのバージョン番号を増やします。アプリケーションが起動すると、比較、番号付け、必要に応じてコードを実行してデータベース構造を更新し、データベースのバージョン番号を更新します。したがって、データベースはアプリケーションで最新の状態になります。私のコードは次のようなものです

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 は、次のような必要なコードを実行するだけです。

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

実際に同じコードを使用して、データベースを最初から作成できます

CreateDatabase;
for i := 1 to AppVersion do
  UpdateStructure(i);
于 2009-11-26T21:54:28.187 に答える