数据迁移工具的使用与实现

在软件开发过程中,经常需要将生产环境的数据迁移到测试环境中,以便测试人员能够使用实际数据量进行测试。本文将介绍如何使用SqlBulkCopy工具进行数据迁移,以及如何通过C#实现一个简单的数据迁移工具。

数据迁移工具概述

数据迁移工具可以帮助将生产环境的数据轻松迁移到测试环境中。使用SqlBulkCopy工具,可以快速地将大量数据迁移到目标数据库。SqlBulkCopy是ADO.NET2.0提供的一个托管类,它类似于BCP工具,但使用起来更加方便。

SqlBulkCopy工具的使用

SqlBulkCopy工具支持SQL Server 2005和SQL Server 2000。它具有以下特点:

  • 可以选择特定的表进行数据迁移
  • 可以删除目标表中现有的数据
  • 在加载数据时报告进度
  • 记录每个表的加载或删除操作结果
  • 可以在处理过程中取消操作,应用程序会在完成当前表后停止加载数据

数据迁移工具的实现

本文介绍的数据迁移工具是一个C#Windows Forms项目。项目非常简单,一个Windows表单完成了所有的工作。它使用BackgroundWorker组件来报告进度。源和目标连接定义在应用程序配置文件中。如果在删除或加载数据时发生任何异常,应用程序会记录异常并继续处理下一个表。

数据迁移工具主要包括两个主要功能:DeleteData和LoadData。

DeleteData功能主要完成以下任务:

  • 禁用所有表的约束
  • 禁用所有表的触发器
  • 从表中删除数据(根据表的外键约束使用DELETE或TRUNCATE语句)
  • 记录结果
  • 启用所有表的约束
  • 启用所有表的触发器
private void DeleteData() { using (SqlConnection conn = new SqlConnection(strDestConn)) { conn.Open(); SqlCommand cmd = conn.CreateCommand(); cmd.CommandTimeout = 0; if (ds != null && ds.Tables[0].Rows.Count > 0) { // 禁用所有表的约束 foreach (DataRow dr in ds.Tables[0].Rows) { cmd.CommandText = "ALTER TABLE [" + dr["TABLE_SCHEMA"].ToString() + "].[" + dr["TABLE_NAME"].ToString() + "] NOCHECK CONSTRAINT ALL"; cmd.CommandText += "ALTER TABLE [" + dr["TABLE_SCHEMA"].ToString() + "].[" + dr["TABLE_NAME"].ToString() + "] DISABLE TRIGGER ALL"; cmd.ExecuteNonQuery(); } // 删除选定表中的数据并记录结果 string strLogFile = "DeleteLog" + DateTime.Now.ToString("MMddyyyyHHmm") + ".txt"; using (StreamWriter sw = new StreamWriter(strLogFile, false)) { sw.AutoFlush = true; foreach (object dr in lstInclude.Items) { try { cmd.CommandText = "SELECT OBJECTPROPERTY (object_id('" + dr.ToString() + "'),'TableHasForeignRef')"; int intref = Convert.ToInt32(cmd.ExecuteScalar()); if (intref == 1) cmd.CommandText = "DELETE FROM " + dr.ToString(); else cmd.CommandText = "TRUNCATE TABLE " + dr.ToString(); cmd.ExecuteNonQuery(); sw.WriteLine("Data deleted successfully from " + dr.ToString() + " at " + DateTime.Now.ToString()); sw.WriteLine(); } catch (Exception ex) { sw.WriteLine("Error while deleting data in table " + dr.ToString() + ".Error is " + ex.Message); sw.WriteLine(); } } } // 启用所有表的约束 foreach (DataRow dr in ds.Tables[0].Rows) { cmd.CommandText = "ALTER TABLE [" + dr["TABLE_SCHEMA"].ToString() + "].[" + dr["TABLE_NAME"].ToString() + "] CHECK CONSTRAINT ALL"; cmd.CommandText += "ALTER TABLE [" + dr["TABLE_SCHEMA"].ToString() + "].[" + dr["TABLE_NAME"].ToString() + "] ENABLE TRIGGER ALL"; cmd.ExecuteNonQuery(); } } } }
  • 从源表中使用SQL数据读取器加载数据
  • 创建SqlBulkCopy对象,并设置KeepIdentity和TableLock选项。锁定表可以加快加载过程。默认情况下,SqlBulkCopy在加载数据时会禁用表的约束和触发器
  • 映射源表和目标表的列。如果两个环境中列的顺序位置不同,这是必要的
  • 在映射列时排除计算列
  • 通过将数据读取器传递给SqlBulkCopy来批量插入数据到表中
private void LoadData(string pSourceConn, string pDestConn, string pTable) { using (SqlConnection srcConn = new SqlConnection(pSourceConn)) { string[] strTable = pTable.Split('.'); // 从源表中获取数据 srcConn.Open(); SqlCommand srcCommand = new SqlCommand("SELECT * FROM " + pTable, srcConn); srcCommand.CommandTimeout = 0; SqlDataReader sqldr = srcCommand.ExecuteReader(); SqlBulkCopy sqlbcp = new SqlBulkCopy(pDestConn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.TableLock); // 映射列 SqlConnection destConn = new SqlConnection(pDestConn); destConn.Open(); SqlCommand cmd1 = new SqlCommand("SELECT COLUMN_NAME, COLUMNPROPERTY(OBJECT_ID('" + strTable[0] + "." + strTable[1] + "'),COLUMN_NAME,'IsComputed')AS 'IsComputed' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '" + strTable[0] + "' AND TABLE_NAME = '" + strTable[1] + "'", destConn); SqlDataReader drcolumns = cmd1.ExecuteReader(); while (drcolumns.Read()) { if (drcolumns.GetInt32(1) != 1) sqlbcp.ColumnMappings.Add(drcolumns.GetString(0), drcolumns.GetString(0)); } drcolumns.Close(); // 加载数据 sqlbcp.BulkCopyTimeout = 0; sqlbcp.DestinationTableName = pTable; sqlbcp.WriteToServer(sqldr); sqldr.Close(); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485