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. 解决com.mysql.jdbc.PacketTooBigException: Packet for query is too large问题

    2017年05月10日 09:45:55 阅读数:1659 在做查询数据库操作时,报了以上错误,原因是MySQL的max_allowed_packet设置过小引起的,我一开始设置的是1M,后来改为了2 ...

  2. 浏览器解析,HTTP/HTTPS、TCP/IP、WebSocket协议

    浏览器相关 浏览器对同一个域名有连接数限制,大部分是 6. 浏览器指的是 Chrome.Firefox,而浏览器内核则是 Blink.Gecko,浏览器内核只负责渲染,GUI 及网络连接等跨平台工作则 ...

  3. LightOJ-1336 Sigma Function 唯一分解定理 巧妙使用sqrt()等算数目

    题目链接:https://cn.vjudge.net/problem/LightOJ-1336 题意 给出一个区间[1, n],求区间内所有数中因数之和为偶数的数目 思路 第二次写这个题 首先想到唯一 ...

  4. luogu P4062 [Code+#1]Yazid 的新生舞会(线段树+套路)

    今天原来是平安夜啊 感觉这题是道好题. 一个套路枚举权值\(x\),把权值等于\(x\)的设为1,不等于的设为-1,然后问题转化为多少个区间权值和大于. 发现并不是很好做,还有一个套路,用前缀和查分来 ...

  5. 仿射变换(Affine Transformation)

    转自:https://www.cnblogs.com/bnuvincent/p/6691189.html http://www.cnblogs.com/ghj1976/p/5199086.html 变 ...

  6. JDBC读写MySQL的大字段数据

    JDBC读写MySQL的大字段数据   不管你是新手还是老手,大字段数据的操作常常令你感到很头痛.因为大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式 来处理的.而非一般的字段 ...

  7. bytes、str与unicode

    1.Python3字符序列的类型 bytes -> 原始的8位值(既字节) str -> Unicode字符 2.Python2字符序列的类型 str -> 原始的8位值(既字节) ...

  8. C语言修改文件某部分内容

    两种方法 1.全部读入内存 修改后重新存入文件 2.边读边写到另一新建文件 要修改的部分修改后存入新建文件 其他部分原封不动写入 写完删掉原先文件 将这个新的改为删掉那个的名字 方法一 读入内存修改 ...

  9. 使用JMX透过防火墙远程监控tomcat服务

    https://my.oschina.net/mye/blog/64879 http://blog.csdn.net/l1028386804/article/details/51547408 http ...

  10. Appium - Android 对照 iOS

    Appium - Android 对照 iOS 作者: Max.Bai 时间: 2014/10 Appium - Android 对照 iOS Appium 支持Android也支持iOS.可是两者还 ...