互不联通的两个数据库的数据同步方法:序列化传输
有这么一个需求:有两个数据在不同的平台上,之间无法直接连接,现需要把一个数据库的内容同步到另一个中去,同时转移过程中需要对数据进行加密。
解决方案一:
就是先从源数据库导出数据至文本文件,对文件进行加密,然后传输,在目标上进行解密和导入操作。该方案中,文本格式使用了首行为列名,使用分隔符隔开字段的方式保存文件,此乃常见的数据导出格式,但由于该数据内容中包含了回车、换行、分号、引号等特殊字符,给文本的读取带来一定的复杂度,无法使用简单的读取一行即为一条记录的方式,最后使用了比较复杂的正则表达式来获取记录。
比较好的解决方案:
使用序列化DataTable对象简化代码复杂度。
数据从源表中读取出来,存放在DataTable中,然后使用BinaryFormatter 对其进行序列化,得到一个文件,对文件加密,传输,在目标接收后反序列化为DataTable,然后就可以使用SqlBulkCopy把数据导入数据库中。使用该方法,最大的好处就是简单,不用再处理复杂的文本格式。
这里有一段测试代码:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stopwatch mytime = new Stopwatch();
mytime.Start();
string connstr = @"server=.\SQLEXPRESS;database=iap_jy;user id=sa;password=lixin520;pooling=true;Timeout=60";
SqlConnection conn = new SqlConnection(connstr);
SqlDataAdapter adp = new SqlDataAdapter("select * from _user", conn);
conn.Open();
DataTable dt = new DataTable();
adp.Fill(dt);
conn.Close();
mytime.Stop();
Console.WriteLine("读取数据行数:"+dt.Rows.Count.ToString());
Console.WriteLine("读取数据花费时间:"+mytime.ElapsedMilliseconds.ToString());
mytime.Restart();
MemoryStream ms = new MemoryStream();
BinaryFormatter myFormatter = new BinaryFormatter();
myFormatter.Serialize(ms, dt);
mytime.Stop();
Console.WriteLine("序列化花费时间:"+mytime.ElapsedMilliseconds.ToString ());
ms.Position = 0;
mytime.Restart();
BinaryFormatter myFormatter2 = new BinaryFormatter();
DataTable dt2 = (DataTable)myFormatter2.Deserialize(ms);
mytime.Stop();
Console.WriteLine("反序列化花费时间:"+mytime.ElapsedMilliseconds.ToString ());
ms.Close();
}
}
}
从代码运行效果来看,序列化的速度还可以接受,如没有特别要求,直接使用该方法就可以了,不用再寻找其他高速的序列化工具如ProtoBuf.net 。