使用Delphi在已安装的应用程序中进行数据库版
我正在研究许多Delphi应用程序,当发布新版本和用户选择安装其他模块时,需要在现场升级自己的数据库结构.应用程序使用各种嵌入式数据库(目前是DBISAM和Jet,但这可能会改变).
在过去,我使用DBISAM使用用户版本号完成此操作,而不是可以存储在每个表中.我发送了一组额外的空数据库文件,并在启动时使用FieldDefs比较每个表的版本号,以便在必要时更新已安装的表.虽然这有效但我发现必须运送数据库的备用副本并且更新版本的DBISAM已经改变了表重组方法,因此我无论如何都需要重写它. 我可以看到两种实现方法:使用数据库存储版本号并使用DDL脚本从旧版本获取更新版本或在应用程序内存储数据库结构的参考版本,比较启动时对数据库的引用up,让应用程序生成DDL命令来升级数据库. 我想我可能要实现两者的一部分.我不希望每次应用程序启动时应用程序都将数据库与引用结构区分开来(太慢),因此我需要一个数据库结构版本号来检测用户是否使用了过时的结构.但是,我不确定我可以信任预先编写的脚本来进行结构升级,因为过去数据库可能已经部分更新,或者用户可能自己更改了数据库结构,所以我倾向于使用实际更新的参考差异. 研究这个问题我发现了一些数据库版本控制工具,但它们似乎都是针对SQL Server的,并且是在实际应用程序之外实现的.我正在寻找一个可以紧密集成到我的应用程序中的流程,可以适应不同的数据库需求(我知道我必须编写适配器,自定义后代类或事件代码来处理各种DDL的差异数据库,这不会打扰我). 有没有人知道任何现成的东西,或者没有做到这一点,有没有人有任何想法: >在应用程序中存储通用关系数据库结构的引用版本的最佳方法. 解决方法
我在这里有一篇关于我如何做
dbisam database versioning和
sql server的博客文章.
重要的部分是:
代码示例是 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; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |