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. luogu P1622 释放囚犯

    题目描述 Caima王国中有一个奇怪的监狱,这个监狱一共有P个牢房,这些牢房一字排开,第i个紧挨着第i+1个(最后一个除外).现在正好牢房是满的. 上级下发了一个释放名单,要求每天释放名单上的一个人. ...

  2. [洛谷P2183]巧克力

    题目大意:有n块巧克力,每块巧克力有一个大小.巧克力可以切成若干份.现在要你切成大小相等的m块,且尽可能大.求这个大小. 解题思路:我们二分巧克力切成的大小,然后计算能切成多少块,判断即可.由于最大的 ...

  3. JavaScript系列——数组元素左右移动N位算法实现

    引言 在自己刚刚毕业不久的时候,去了一家公司面试,面试官现场考了我这道题,我记忆深刻,当时没有想到思路,毫无疑问被面试官当成菜鸟了.最近刚好在研究数组的各种算法实现,就想到这道题,可以拿来实现一下,纪 ...

  4. [HAOI2015]树上染色(树形dp)

    [HAOI2015]树上染色 题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所 ...

  5. 【推荐系统实战】:C++实现基于用户的协同过滤(UserCollaborativeFilter)

    好早的时候就打算写这篇文章,可是还是參加阿里大数据竞赛的第一季三月份的时候实验就完毕了.硬生生是拖到了十一假期.自己也是醉了... 找工作不是非常顺利,希望写点东西回想一下知识.然后再攒点人品吧,仅仅 ...

  6. HDU4324 Triangle LOVE【拓扑排序】

    Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  7. POJ 2739 Sum of Consecutive Prime Numbers(素数)

    POJ 2739 Sum of Consecutive Prime Numbers(素数) http://poj.org/problem? id=2739 题意: 给你一个10000以内的自然数X.然 ...

  8. JavaScript编程随笔

    尽管说用JS非常多年了,可是却一直停留在肤浅的阶段,对JS的机制原理依旧是一知半解,比如:闭包.尽管能说出一二.却不能说出三四,确实羞愧.近期恶补一番.并将比較与大家分享,希望对大家有些帮助. 闭包 ...

  9. Vue Syntax Highlight

    Vue Syntax Highlight https://github.com/vuejs/vue-syntax-highlight

  10. 安卓第一课:android studio 的环境搭建与真机运行以及遇到的问题

    AS的下载: https://developer.android.com/studio/index.html AS的安装: android studio, sdk, virtual device都要安 ...