跨数据库迁移与代码生成工具开发

在软件开发过程中,经常需要处理不同数据库之间的数据迁移问题。本文将介绍一个实际案例,说明在迁移过程中遇到的问题及其解决方案,并展示如何使用C#WPF开发一个代码生成工具来自动化处理这些问题。

正在构建的应用程序需要存储大量LOB数据,这些数据分散在多个数据库中。根据用户的授权级别,他们可能只能访问一个或多个数据库(有时甚至是数据库的子集)。因此,需要一个中央数据存储来保存安全信息、完整的安装信息以及LOB数据库的位置和数据内容。称这个数据存储为“仓库”(Repository),并规定任何需要跨LOB数据库边界的数据都应该存储在仓库中。

早期项目构建

在项目的早期阶段,构建了一个基于Entity Framework的WCF服务,它允许以通用的方式对LOB数据库执行任何数据操作。为了实现这一点,构建了一个代码生成器来生成所需的所有业务类。服务代码生成过程基于这样一个事实:使用的是一个自动生成的EF模型。换句话说,EF模型是SQL Server数据模型的直接映射。因此,可以从SQL Server提取元数据来为代码生成过程提供数据。为此,数据库团队构建了一个脚本,用于从SQL Server提取元数据(使用系统视图)并将其插入到一个单独的数据库中,使用这个数据库来驱动代码生成。

迁移过程中的问题

在恢复元数据库后,问题开始了。需要修改提取元数据的存储过程,将源数据库名称更改为使其访问仓库数据库。但是,当运行修改存储过程的语句时,出现了多个排序冲突错误。事实证明,从仓库数据库获得的备份是在与通常使用的不同的排序规则下创建的。具体来说,仓库数据库是使用Latin1_General_CI_AS(本地默认设置)创建的,而元数据库是使用SQL_Latin1_General_CP1_CI_AS创建的。

解决方案

为了解决这个问题,需要逐列更改排序规则。由于从仓库访问的唯一数据是在系统视图中,不能(也不想)更改它们的排序规则,所以不得不更改元数据库上的排序规则。不太愿意手动完成这项工作,而且由于预见到这种情况会经常发生,认为最好编写一个小工具来为处理这个问题。以下是该工具的屏幕截图:

它允许输入一个SQL实例名称,之后它会从该实例检索数据库列表,并检索所有可用的排序规则以填充两个组合框。一旦选择了一个数据库和至少一个源排序规则,就可以点击“查找列”按钮来检索任何具有源排序规则的列。在选择了目标排序规则并取消选中不想更改的任何列之后,可以点击“更改排序规则”按钮,它将触发一个alter table / alter column查询,尝试为完成这个操作。

代码实现

这个工具的亮点之一是直接在ADO上使用了一些查询。以下是这些查询的代码片段:

private const string GetAllDatabasesSqlCommand = @" select name from sys.databases "; private const string GetAllCollationsSqlCommand = _ @" select name from ::fn_helpcollations() "; private const string GetAllColumnNamesSqlCommand = _ @" select o.name, c.name, t.name, c.max_length, c.is_nullable from sys.columns c left join sys.objects o on c.object_id=o.object_id left join sys.types t on c.system_type_id = t.system_type_id where c.collation_name=@collation_name ";

第一个查询检索所有数据库名称。这显然只有在连接到主数据库时才有效。第二个查询返回所有排序规则名称。这可以在任何数据库上完成(它应该总是返回相同的列表)。最后一个查询找到使用特定排序规则的所有列。结果集包括表名、列名、类型名、最大长度以及列是否可以包含NULL。这是生成alter table alter column语句所需的所有信息,该语句只更改排序规则。

以前从未使用过的是SqlConnectionStringBuilder类,它用于动态创建连接字符串。以下是为此使用的代码:

SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(); connectionStringBuilder.DataSource = hostnameTextBox.Text; connectionStringBuilder.InitialCatalog = MasterDatabaseName; connectionStringBuilder.IntegratedSecurity = true;
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485