SQL Server数据全同步[终结版]

版权全部。转载请注明出处。谢谢!

经过两天的同步编写和測试。出了第一个Release版本号:

1. 本函数仅支持单向同步。即从一个主数据库想多个从数据库同步

2.主数据库的不论什么增删改都会同步到全部从数据库上

3. 最重要的一点:同步数据库的价值所在:当主数据库server不可用时,程序能够使用其它从数据库或者备用数据库,这对于未来公有云和私有云应用具有重大价值!

代码:

<span style="font-size:18px;">/// <summary>
/// Note: for columns, the first string must be primary key name!
/// </summary>
/// <param name="server"></param>
/// <param name="database"></param>
/// <param name="uid"></param>
/// <param name="password"></param>
/// <param name="tableName"></param>
/// <param name="columns"></param>
/// <param name="ignoreUpdateColumns"></param>
/// <param name="ignoreInsertColumns"></param>
public void BulkUpdateTo(string server, string database, string uid, string password, string tableName, List<string> columns, List<string> ignoreUpdateColumns, List<string> ignoreInsertColumns)
{
string primaryKeyName = columns[0];
string connectionString = "Server=" + server + ";Database=" + database + ";User Id=" + uid + ";Password=" + password;
// Create destination connection
SqlConnection destinationConnector = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand("SELECT * FROM " + tableName, destinationConnector);
// Open source and destination connections.
this.EnsureConnectionIsOpen();
destinationConnector.Open(); Dictionary<int, string> Index_PrimaryKeyValue = new Dictionary<int, string>(); SqlDataReader readerSource = cmd.ExecuteReader();
Dictionary<string, Dictionary<string, string>> recordsDest = new Dictionary<string, Dictionary<string, string>>();
int i = 0;
while (readerSource.Read())
{
Index_PrimaryKeyValue.Add(i, readerSource[primaryKeyName].ToString());
string recordIndex = Index_PrimaryKeyValue[i];
recordsDest[recordIndex] = new Dictionary<string, string>();
foreach (string keyName in columns)
{
recordsDest[recordIndex].Add(keyName, readerSource[keyName].ToString());
}
i++;
} // Select data from Products table
cmd = new SqlCommand("SELECT * FROM " + tableName, mySqlConn);
// Execute reader
SqlDataReader reader = cmd.ExecuteReader();
Dictionary<string, Dictionary<string, string>> recordsSource = new Dictionary<string, Dictionary<string, string>>(); Dictionary<int, string> Index_PrimaryKeyValue2 = new Dictionary<int, string>(); int j = 0;
while (reader.Read())
{
Index_PrimaryKeyValue2.Add(j, reader[primaryKeyName].ToString());
string recordIndex = Index_PrimaryKeyValue2[j];
recordsSource[recordIndex] = new Dictionary<string, string>();
foreach (string keyName in columns)
{
recordsSource[recordIndex].Add(keyName, reader[keyName].ToString());
}
j++;
}
reader.Close();
readerSource.Close(); foreach (var record in recordsSource)
{
string setScripts = string.Empty;
string insertKeysScripts = string.Empty;
string insertValuesScripts = string.Empty;
int setScriptsIndex = 0;
int insertScriptsIndex = 0;
string primaryKeyValue = record.Key;
if (recordsDest.ContainsKey(primaryKeyValue))
{
foreach (string keyName in columns)
{
if (!ignoreUpdateColumns.Contains(keyName))
{
if (recordsDest[primaryKeyValue][keyName] == record.Value[keyName])
{
//do nothing
}
else
{
if (setScriptsIndex == 0)
{
setScripts += keyName + "='" + recordsSource[primaryKeyValue][keyName] + "' ";
}
else
{
setScripts += "," + keyName + "='" + recordsSource[primaryKeyValue][keyName] + "' ";
}
setScriptsIndex++;
}
}
}
}
else
{
foreach (string keyName in columns)
{
if (!ignoreInsertColumns.Contains(keyName))
{
if (insertScriptsIndex == 0)
{
insertKeysScripts += keyName;
insertValuesScripts += "'" + recordsSource[primaryKeyValue][keyName] + "' ";
}
else
{
insertKeysScripts += "," + keyName;
insertValuesScripts += ",'" + recordsSource[primaryKeyValue][keyName] + "' ";
}
insertScriptsIndex++;
}
}
} //update source to dest
if (setScriptsIndex > 0)
{
cmd = new SqlCommand("Update " + tableName + " set " + setScripts + " where " + primaryKeyName + "='" + recordsSource[primaryKeyValue][primaryKeyName] + "'", destinationConnector);
cmd.ExecuteNonQuery();
} //insert source to dest
if (insertScriptsIndex > 0)
{
cmd = new SqlCommand("insert into " + tableName + " (" + insertKeysScripts + ") values (" + insertValuesScripts + ")", destinationConnector);
cmd.ExecuteNonQuery();
}
} //after update and insert, the count still not match, means we delete some records in source db, then we also need to delete the records in destination db
foreach (var re in recordsDest)
{
//get the delete record primary key value
if (!recordsSource.ContainsKey(re.Key))
{
cmd = new SqlCommand("delete from " + tableName + " where " + primaryKeyName + "='" + re.Value[primaryKeyName].ToString() + "'", destinationConnector);
cmd.ExecuteNonQuery();
}
} // Close objects
destinationConnector.Close();
mySqlConn.Close();
}</span>

代码的基础类其它部分请看下列文章:

1. C#同步SQL Server数据库中的数据--数据库同步工具[同步已有的有变化的数据]

2.分析下自己写的SQL Server同步工具的性能和缺陷

SQL Server数据全同步及价值分析[终结版]的更多相关文章

  1. SQL Server 复制 - 发布订阅(SQL Server 数据同步)

    原文:SQL Server 复制 - 发布订阅(SQL Server 数据同步) SQL Server的同步是通过SQL Server自带的复制工具来实现的,分发布和订阅2大步. A,复制-发布 发布 ...

  2. Docker-compose搭建ELK环境并同步MS SQL Server数据

    前言 本文作为学习记录,供大家参考:一次使用阿里云(Aliyun)1核2G centos7.5 云主机搭建Docker下的ELK环境,并导入MS SQL Server的商品数据以供Kibana展示的配 ...

  3. Oracle DBLink跨数据库访问SQL server数据同步 踩坑实录

    项目需求:这里暂且叫A公司吧,A公司有一套人事管理软件,需要与我们公司的软件做人员信息同步,A公司用的是SQL server数据库,我们公司用的Oracle,接口都不会开发(一万句"fuck ...

  4. SQL Server 2008 数据库同步的两种方式 (发布、订阅)

    参考转载: SQL Server 2008 数据库同步的两种方式 (发布.订阅) 使用Sqlserver事务发布实现数据同步

  5. Sql Server函数全解<五>之系统函数

    原文:Sql Server函数全解<五>之系统函数  系统信息包括当前使用的数据库名称,主机名,系统错误消息以及用户名称等内容.使用SQL SERVER中的系统函数可以在需要的时候获取这些 ...

  6. 浅谈SQL Server数据内部表现形式

    在上篇文章 浅谈SQL Server内部运行机制 中,与大家分享了SQL Server内部运行机制,通过上次的分享,相信大家已经能解决如下几个问题: 1.SQL Server 体系结构由哪几部分组成? ...

  7. SQL server数据缓存依赖

    SQL server数据缓存依赖有两种实现模式,轮询模式,通知模式. 1  轮询模式实现步骤 此模式需要SQL SERVER 7.0/2000/2005版本以上版本都支持        主要包含以下几 ...

  8. [SQL]SQL Server数据表的基础知识与增查删改

    SQL Server数据表的基础知识与增查删改 由张晨辉(学生) 于19天 前发表 | 阅读94次 一.常用数据类型 .整型:bigint.int.smallint.tinyint .小数:decim ...

  9. Sql Server数据的加密与解密

    Sql Server数据的加密与解密 在sql server中,我们如何为数据进行加密与解密,避免使用者窃取机密数据? 对于一些敏感数据,如密码.卡号,一般不能使用正常数值来存储.否则会有安全隐患.以 ...

随机推荐

  1. 正则表达式中的/i

    i = insensitive means case-insensitive 表示大小写不敏感

  2. 微信小程序微信支付的一些坑

    使用的是Node.js作为后端 统一下单: appid:这里的appid是调起微信支付的appid mch_id:商户号,需要注意的是商户号要与appid对应 nonce_str:Math.rando ...

  3. 通过nodeSelector配置项实现pod部署至指定node

    Node节点添加标签 [root@node1 work]# kubectl label nodes node1 node=master --overwrite node/node1 labeled [ ...

  4. Geany IDE搭建

    http://blog.sina.com.cn/s/blog_567e650201010x5e.html

  5. Qt之pro配置多个子工程/子模块

    简述 进行Qt项目开发的时候,尤其是大型项目,经常涉及多工程/多模块问题,其主要思想还是模块化,目的是为了降低程序复杂度,使程序设计.调试和维护等操作简单化. 简述 配置 效果 多工程 多模块 更多参 ...

  6. C++模板遇到iterator时候遇到的问题和解决方法

    今天开发的时候,发现用模板的时候,再加上iterator,会报错,如下: std::map<T, S>::iterator find_iter = mp.find(key); 编译会报错: ...

  7. 【linux驱动分析】misc设备驱动

    misc设备驱动.又称混杂设备驱动. misc设备驱动共享一个设备驱动号MISC_MAJOR.它在include\linux\major.h中定义:         #define MISC_MAJO ...

  8. 【POJ 1845】 Sumdiv (整数唯分+约数和公式+二分等比数列前n项和+同余)

    [POJ 1845] Sumdiv 用的东西挺全 最主要通过这个题学了约数和公式跟二分求等比数列前n项和 另一种小优化的整数拆分  整数的唯一分解定理: 随意正整数都有且仅仅有一种方式写出其素因子的乘 ...

  9. Mongodb集群之副本集

    上篇咱们遗留了几个问题 1主节点是否能自己主动切换连接? 眼下须要手动切换 2主节点读写压力过大怎样解决 3从节点每一个上面的数据都是对数据库全量拷贝,从节点压力会不会过大 4数据压力达到机器支撑不了 ...

  10. ajax无刷新翻页后,jquery失效问题的解决

    例如 $(".entry-title a").click(function () {   只对第一页有效, 修改为 $(document).on('click', ".e ...