加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

使用Delphi在已安装的应用程序中进行数据库版

发布时间:2020-12-15 04:09:04 所属栏目:大数据 来源:网络整理
导读:我正在研究许多Delphi应用程序,当发布新版本和用户选择安装其他模块时,需要在现场升级自己的数据库结构.应用程序使用各种嵌入式数据库(目前是DBISAM和Jet,但这可能会改变). 在过去,我使用DBISAM使用用户版本号完成此操作,而不是可以存储在每个表中.我发送了
我正在研究许多Delphi应用程序,当发布新版本和用户选择安装其他模块时,需要在现场升级自己的数据库结构.应用程序使用各种嵌入式数据库(目前是DBISAM和Jet,但这可能会改变).

在过去,我使用DBISAM使用用户版本号完成此操作,而不是可以存储在每个表中.我发送了一组额外的空数据库文件,并在启动时使用FieldDefs比较每个表的版本号,以便在必要时更新已安装的表.虽然这有效但我发现必须运送数据库的备用副本并且更新版本的DBISAM已经改变了表重组方法,因此我无论如何都需要重写它.

我可以看到两种实现方法:使用数据库存储版本号并使用DDL脚本从旧版本获取更新版本或在应用程序内存储数据库结构的参考版本,比较启动时对数据库的引用up,让应用程序生成DDL命令来升级数据库.

我想我可能要实现两者的一部分.我不希望每次应用程序启动时应用程序都将数据库与引用结构区分开来(太慢),因此我需要一个数据库结构版本号来检测用户是否使用了过时的结构.但是,我不确定我可以信任预先编写的脚本来进行结构升级,因为过去数据库可能已经部分更新,或者用户可能自己更改了数据库结构,所以我倾向于使用实际更新的参考差异.

研究这个问题我发现了一些数据库版本控制工具,但它们似乎都是针对SQL Server的,并且是在实际应用程序之外实现的.我正在寻找一个可以紧密集成到我的应用程序中的流程,可以适应不同的数据库需求(我知道我必须编写适配器,自定义后代类或事件代码来处理各种DDL的差异数据库,这不会打扰我).

有没有人知道任何现成的东西,或者没有做到这一点,有没有人有任何想法:

>在应用程序中存储通用关系数据库结构的引用版本的最佳方法.
>针对实际数据库区分引用的最佳方法.
>生成DDL以更新数据库的最佳方法.

解决方法

我在这里有一篇关于我如何做 dbisam database versioning和 sql server的博客文章.

重要的部分是:

Because dbisam doesn’t support views,
the version number is stored (along
with a bunch of other info) in an ini
file in the database directory.

I have a datamodule,
TdmodCheckDatabase. This has a
TdbisamTable component for every table
in the database. The table component
contains all fields in the table and
is updated whenever the table is
changed.

To make database changes,the
following process was used:

  1. Increase the version number in the application
  2. Make and test DB changes.
  3. Update the affected tables in TdmodCheckDatabase
  4. If necessary (rarely) add further upgrade queries to
    TdmodCheckDatabase. E.g. to set the
    values of new fields,or to add new
    data rows.
  5. Generate a CreateDatabase unit script using the supplied database
    tools.
  6. Update unit tests to suit the new db

When the application is run,it goes
through the following process

  1. If no database is found,then run CreateDatabase unit and then do
    step 3
  2. Get the current version number from the database ini file
  3. If it is less than the expected version number then
    Run CreateDatabase (to create any new tables)
    Check every table component in TdmodCheckDatabase
    Apply any table changes
    run any manual upgrade scripts
  4. Update the version number in the database ini file

代码示例是

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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读