项目环境:公司中心有一个数据库,产品部署地有多个,每个部署地是一个局域网,部署地内有一台对外通讯的服务器(可能会断网)。项目需要将每个部署地的部分数据,同步到中心数据库。

基本思路:在需要同步的数据库的说明中添加Update标识,在需要同步的表中添加UpdateDate字段。在每一天的0点时候,会执行一次同步,根据UpdateDate字段进行时间比对,同步会遍历当前数据库的所以后表,如果表中包含Update标识,就执行同步操作。同步时执行事务操作,全部数据同步完成后进行提交操作。如果有错误,则执行RollBack,并发送邮件通知维护人员。

本地数据库LocalDB

远端数据库RemoteDB

表名 TableName

主键PrimaryKey

简要步奏

0. BeginTrans

LocalDB:

1  从LocalDB读出DateTable

RemoteDB:

2. 数据库使用select * into tmpTable from TableName where PrimaryKey=-1 生成临时表

3. 将数据集提交到临时表中

4. 
---更新相同数据 / 删除相同数据  二选一即可
 --更新(需要对知道每个表的哪些字段需要更新)
update TableName set CreateDate=A.CreateDate from tmpTable A,TableName B where B.PrimaryKey=A.PrimaryKey

--删除

delete from TableName  where PrimaryKey in (select PrimaryKey from tmpTable)

---插入不同数据的记录
insert into TableName   select * from tmpTable A where not exists(select PrimaryKey  from TableName   B where B.{1}=A.PrimaryKey )
5. 跳到第一步 直到所有表都更新完成

6. Commit

public class Base_TableUpdate{public int Run(DateTime lastUpdateDate){IDatabase dbRemote = null;int updateCount = 0;try{IDatabase dbLocal = DataFactory.Database("LocalSqlServer");dbRemote = DataFactory.Database("RemoteSqlServer");DbTransaction trans = dbRemote.BeginTrans();//查询出所有表/*selectROW_NUMBER() OVER (ORDER BY a.object_id) AS No, a.name AS TableName,isnull(g.[value],'') AS Explainfromsys.tables a left join sys.extended_properties gon (a.object_id = g.major_id AND g.minor_id = 0)*/string sql = string.Format("select ROW_NUMBER() OVER (ORDER BY a.object_id) AS No, a.name AS TableName, isnull(g.[value],'') AS Explain  from sys.tables a left join sys.extended_properties g on (a.object_id = g.major_id AND g.minor_id = 0)");List<TableNameEntity> list = dbLocal.FindListBySql<TableNameEntity>(sql);foreach(TableNameEntity en in list){if (string.IsNullOrEmpty(en.Explain) || !en.Explain.ToLower().Contains("update"))continue;string tableName = en.TableName;//1 查出数据//where UpdateDate>'{1}'DataSet ds = dbLocal.FindDataSetBySql(string.Format("select * from {0} where UpdateDate>'{1}'", tableName, lastUpdateDate.ToString("yyyy-MM-dd hh:mm:ss")));updateCount += ds.Tables[0].Rows.Count;//2 创建临时表int res = dbRemote.FindCountBySql("select Count(Name) from sysobjects where name='tmpTable'");if (res == -1){//失败throw new Exception("10001 查询临时表时失败,Code{ dbLocal.FindCountBySql(\"select Count(Name) from sysobjects where name='tmpTable'\"); }");}else if (res == 1){//表存在,删除表dbRemote.ExecuteBySql(new StringBuilder("Drop Table tmpTable"));}//创建StringBuilder sb = new StringBuilder();sb.AppendFormat("select * into tmpTable from {0} where (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='{0}') is null", tableName);res = dbRemote.ExecuteBySql(sb);if (res == -1){throw new Exception("10002 创建临时表时失败,Code{ sb.AppendFormat(\"select * into tmpTable from {0} where (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='{0}') is null\", tableName);dbRemote.ExecuteBySql(sb); }");}//3 往临时表插入数据//获得表主键sb = new StringBuilder();sb.AppendFormat("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='{0}'", tableName);PrimaryKeyEntity entity = dbRemote.FindEntityBySql<PrimaryKeyEntity>(sb.ToString());string primaryKey = entity.COLUMN_NAME;if (string.IsNullOrEmpty(primaryKey)){string errmsg = string.Format("10006 表主键为空,Code{ sb.AppendFormat(\"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='{0}'\", tableName); } Parameter{ tableName:{0}}", tableName);throw new Exception(errmsg);}//插入所有数据ds.Tables[0].TableName = "tmpTable";bool bInRes = dbRemote.BulkInsert(ds.Tables[0], trans);if (!bInRes){string errmsg = string.Format("10003 插入所有数据时失败,Code{ ds.Tables[0].TableName = \"tmpTable\";bool bInRes = dbRemote.BulkInsert(ds.Tables[0], trans); }");throw new Exception(errmsg);}//4 合并临时表与服务器对应表数据//删除已有数据//delete from ' + @TableName + ' where ' + @PKey + ' in (select ' + @PKey + ' from tmpTable)sb = new StringBuilder();sb.AppendFormat("delete from {0} where {1} in (select {1} from tmpTable)", tableName, primaryKey);res = dbRemote.ExecuteBySql(sb, trans);if (res == -1){string errmsg = string.Format("10004 删除已有数据时失败,Code{ sb.AppendFormat(\"delete from {0} where {1} in (select {1} from tmpTable)\", tableName, primaryKey);res =dbRemote.ExecuteBySql(sb); } Parameter{ tableName:{0}, primaryKey:{1}}", tableName, primaryKey);throw new Exception(errmsg);}//将数据插入表//insert into tmpTable select * from ' + @TableName + ' A where not exists(select ' + @PKey + ' from tmpTable B where B.' + @PKey + '=A.' + @PKey + ')';sb = new StringBuilder();sb.AppendFormat("insert into {0} select * from tmpTable A where not exists(select {1} from {0} B where B.{1}=A.{1})", tableName, primaryKey);res = dbRemote.ExecuteBySql(sb, trans);if (res == -1){string errmsg = string.Format("10005 合并数据时失败,Code{ sb.AppendFormat(\"insert into {0} select * from tmpTable A where not exists(select {1} from {0} B where B.{1}=A.{1})\", tableName, primaryKey);res = dbRemote.ExecuteBySql(sb); } Parameter{ tableName:{0}, primaryKey:{1}}", tableName, primaryKey);throw new Exception(errmsg);}//5 删除临时表dbRemote.ExecuteBySql(new StringBuilder("Drop Table tmpTable"));}dbRemote.Commit();return updateCount;}catch(Exception ex){try{ dbRemote.Rollback(); } catch { }throw ex;}}}public class PrimaryKeyEntity{private string _COLUMN_NAME;/// <summary>/// 表的主键名/// </summary>public string COLUMN_NAME{get { return _COLUMN_NAME; }set { _COLUMN_NAME = value; }}}public class TableNameEntity{private string _TableName;public string TableName{get { return _TableName; }set { _TableName = value; }}private string _Explain;public string Explain{get { return _Explain; }set { _Explain = value; }}}

内外网数据库同步方式相关推荐

  1. 使用proxy实现内网穿透,配置内外网数据库互为主从同步数据

    一.使用proxy实现内网穿透 准备 教程参考地址:https://snail007.github.io/goproxy/manual/zh/#/ proxy软件的git地址:https://gith ...

  2. 关于内外网数据同步解决方案

    目前,越来越多的企业内部或者合作企业之间要求各种业务数据能够实时同步共享,大部分重视安全性的企业会将数据存储至云端以防丢失.高需求企业一般都采用基于TCP的文件复制或同步工具的方法来实现数据同步. 传 ...

  3. SQL Server主从数据库同步方式及同步问题解决方案总结

    SQL Server主从数据库同步方式及同步问题解决方案总结 参考文章: (1)SQL Server主从数据库同步方式及同步问题解决方案总结 (2)https://www.cnblogs.com/zh ...

  4. SQL Server数据库同步方式总结 VS Beedup

    数据库实时同步时下技术热点亦难点,多数企业选择使用数据库SQL Server自带辅助功能,如下总结:      同步方式 功能参数 SQL Server数据库同步方式 国产商业产品 数据库镜像 日志传 ...

  5. 不同数据库同步方式|异地数据库同步|mysql数据库实时同步工具|数据库实时同步

    SyncNavigator v8.6.2 SyncNavigator是一款功能强大的数据库同步软件,适用于SQL SERVER, MySQL,具有自动/定时同步数据.无人值守.故障自动恢复.同构/异构 ...

  6. sql线上线下数据库同步方式

    使用工具Navicat,实现线上和线下数据的数据同步.通过Navicat分别连上线上和线下的数据库,按照如下操作: 1.选中数据库右键,选择数据传输 2.选择需要同步的信息&选择目标数据库 3 ...

  7. SQL SERVER 2008 利用发布订阅方式实现数据库同步

    数据库同步方式有很多种,这里以SQL Server 2008 为例利用数据库发布和订阅的方式来演示数据库的同步技术.由于就有一台计算机,只能在同一个服务器下两个不同的数据库之间进行数据同步进行演示. ...

  8. 数据库同步有哪些方式?【怎么保障目标和源数据一致性】

    文章目录 摘要 一.几种主流的数据库同步方式 二.架构及工作原理 三.全量同步和实时增量同步机制 四.源和目标 五.举例:Oracle 数据实时同步到 Elasticsearch 六.目标和源数据一致 ...

  9. 采用网闸隔离的内外网如何进行数据的即时交互?

    网闸,也称边界平台.内外网数据交换系统. 网闸将内网与外网实现了隔离,即内外网程序不能直接相互访问. 那么,如何实现内外网即时数据交互呢?比如外网程序要访问内网webservice服务? 就拿外网程序 ...

最新文章

  1. Linux分区的认识
  2. 机器学习与深度学习常见面试问题与答案
  3. php制作本地程序,PHP安装程序制作
  4. Selenium3自动化测试——1. 新建第一个Selenium自动化测试脚本
  5. 按照linux文件出现的时间来删除文件
  6. iPhone开发入门守则:Objective-C编码规范--系列教程
  7. SQL查询过滤Where子句用法
  8. linux常用指令总结一~~
  9. Java高并发编程详解系列-线程异常处理
  10. 关于oc中自动引用计数 小结
  11. window docker TensorFlow环境搭建
  12. Linux 进程热升级 共享库的动态替换
  13. live2d_Live2D | CubismSdkForUnity4r.1简介(上)
  14. 【数据结构1800题 (陈守孔) 第2章】线性表 算法设计题全解
  15. 每个设计师都应该了解的IOS编年史
  16. CTF比赛必备常用工具
  17. UBUNTU-Mplay
  18. Linux脚本开头#!/bin/bash和#!/bin/sh是什么意思以及区别
  19. 基于Java机器学习自学笔记(第81-87天:CNN卷积神经网络的入门到全代码编写)
  20. [创投新闻] [中英双语] FACEBOOK为美竞选上线电子投票功能并开通选民信息中心

热门文章

  1. 乘数智之风,为世界造舟筏:女性在当下如何创造?
  2. 爱情公寓4不断刷新记录 大数据成就网络神剧
  3. 如何把笔记本做台式机的副屏(一套键鼠控制两台电脑)
  4. expect用法介绍
  5. 直三棱柱的表面展开图是什么形状的?
  6. Java小程序动态雪花屏保
  7. 手机上如何批量给抖音视频加速
  8. css 滚动条导致padding-right失效
  9. 没病千万别做外包,狗都不如!
  10. 20220314在MT6739的android8.1下打开gpio节点