两个数据库通过DataTable实现差异传输
两个主要方法
/// <summary>
/// 用途:
/// 用源表和目标表比较,返回差异的数据(目标表为参照物)
///
/// 逻辑:
/// 1、合并两个表
/// 2、循环合并后得到的表,判断是否在目标表中存在,如果不存在,则是新增的,RowState为设置为ADD,如果存在,RowState设置为Modify
/// </summary>
/// <param name="sourceTable">源表</param>
/// <param name="targetTable">目标表</param>
/// <param name="primaryKeyColumn">主键字段</param>
/// <returns>差异数据的DataTable,该DataTable中必须有TableName属性,而且是跟数据库中的表一致的</returns>
private DataTable GetDataTableExceptData(DataTable sourceTable,DataTable targetTable,string tableName,string primaryKeyColumn)
{
DataTable dtExcept = new DataTable(sourceTable.TableName);
try
{
dtExcept = sourceTable.AsEnumerable().Except(targetTable.AsEnumerable(),DataRowComparer.Default).CopyToDataTable();
}
catch (Exception)
{
}
for (int i = 0; i < dtExcept.Rows.Count; i++)
{
object obj = dtExcept.Rows[i][primaryKeyColumn];
targetTable.DefaultView.Sort = primaryKeyColumn;
int count = targetTable.DefaultView.Find(obj);
if (count >= 0)
{
dtExcept.Rows[i].SetModified();
}else{
dtExcept.Rows[i].SetAdded();
}
}
dtExcept.TableName = tableName;
return dtExcept;
}
/// <summary>
/// 用途:
/// 根据DataTable 获取SQL脚本
///
/// 逻辑:
/// 1、先判断是否是自动曾长的,如果是自动增长,先关闭自动增长
/// </summary>
/// <param name="dt">源DataTable与目标DataTable的差异</param>
/// <param name="primaryKeyColumn">主键字段</param>
/// <param name="isIdentity">是否自动增长</param>
/// <returns>SQL脚本</returns>
private StringBuilder GetScriptByDataTable(DataTable dt, string primaryKeyColumn,bool isIdentity)
{
StringBuilder sb = new StringBuilder("");
// 开启自动增长时能进行插入数据,后面对应有关闭
if (isIdentity)
{
sb.AppendLine();
sb.Append("-- ===========================" + dt.TableName + "===============================");
sb.AppendLine();
sb.Append("SET IDENTITY_INSERT " + dt.TableName + " ON");
}
if (dt.TableName == "")
{
DialogResult result = MessageBox.Show("DataTable 的 TableName 未指定");
return null;
}
List<string> list_Column = new List<string>();
foreach (DataColumn item in dt.Columns)
{
list_Column.Add(item.ColumnName);
}
for (int i = 0; i < dt.Rows.Count; i++)
{
StringBuilder sb_Insert = new StringBuilder("");
DataRowState rowState = dt.Rows[i].RowState;
if (rowState == DataRowState.Added)
{
StringBuilder sb_Column = new StringBuilder();
StringBuilder sb_Values = new StringBuilder();
sb_Insert.AppendLine();
sb_Insert.Append("INSERT INTO " + dt.TableName + "(");
for (int m = 0; m < list_Column.Count; m++)
{
sb_Column.Append("," + list_Column[m]);
sb_Values.Append(",'" + dt.Rows[i][list_Column[m]]+"'");
}
sb_Insert.Append(sb_Column.ToString());
sb_Insert.Append(") VALUES(");
sb_Insert.Append(sb_Values.ToString());
sb_Insert.Append(");");
sb_Insert.Replace("INSERT INTO "+ dt.TableName +"(,", "INSERT INTO "+ dt.TableName +"(");
sb_Insert.Replace("VALUES(,", "VALUES(");
sb.Append(sb_Insert.ToString());
}
if (rowState == DataRowState.Modified)
{
StringBuilder sb_Update = new StringBuilder("");
sb_Update.AppendLine();
sb_Update.Append("UPDATE " + dt.TableName + " SET ");
for (int k = 0; k < list_Column.Count; k++)
{
if (list_Column[k] != primaryKeyColumn)
{
sb_Update.Append("," + list_Column[k] + "='" + dt.Rows[i][list_Column[k]] + "'");
}
}
sb_Update.Replace("SET ,", "SET ");
sb_Update.Append(" WHERE " + primaryKeyColumn + " = '" + dt.Rows[i][primaryKeyColumn] + "';");
sb.Append(sb_Update.ToString());
}
if (i > 0 && i % 100 == 0)
{
sb.AppendLine();
sb.Append("GO;");
sb.AppendLine();
}
}
// 关闭自动增长时能进行插入数据,前面对应有开启
if (isIdentity)
{
sb.AppendLine();
sb.Append("SET IDENTITY_INSERT " + dt.TableName + " OFF");
}
return sb;
}
=========================================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace IT_Tools
{
public partial class FormOATransmission : Form
{
/// <summary>
/// 源数据库链接
/// </summary>
private static string ConnectionString_Source = ConfigurationManager.AppSettings["DB_Source"].ToString().Trim(); // 开发机
/// <summary>
/// 目标数据库链接
/// </summary>
private static string ConnectionString_Target = ConfigurationManager.AppSettings["DB_Target"].ToString().Trim(); // 生产机
/// <summary>
/// 需要更新的表集合
/// </summary>
private static ArrayList tableList = new ArrayList();
public FormOATransmission()
{
InitializeComponent();
}
// 两个环境的表对比
private void btnDbCompare_Click(object sender, EventArgs e)
{
string strTableName = ""; // 当前表名称,用于表集合循环
string strPrimaryKeyColumn = "";// 当前表主键字段,用于表集合循环
bool isIdentity=false; // 是否自动曾长,用于表集合循环
DataTable dtSource = null; // 用于存放源表的数据,结构和表名称与目标表一致
DataTable dtTarget = null; // 用于存放目标表的数据,结构和表名称与源表一致
DataTable dt = null;
StringBuilder sb_CurrentTableScript = null;
StringBuilder sb_AllTableScript = new StringBuilder();
DataTable dtTableList = GetTableList(); //获取需要更新的表集合
for (int i = 0; i < dtTableList.Rows.Count; i++)
{
strTableName = dtTableList.Rows[i]["TableName"].ToString();
string sql = "select * from " + strTableName;
dtSource = SqlHelper.ExecuteDataset(ConnectionString_Source, CommandType.Text, sql).Tables[0];
dtTarget = SqlHelper.ExecuteDataset(ConnectionString_Target, CommandType.Text, sql).Tables[0];
strPrimaryKeyColumn = dtTableList.Rows[i]["PrimaryKeyColumn"].ToString();
isIdentity = bool.Parse(dtTableList.Rows[i]["IsIdentity"].ToString());
dt = GetDataTableExceptData(dtSource, dtTarget, strTableName, strPrimaryKeyColumn);
if (dt.Rows.Count > 0)
{
sb_CurrentTableScript = GetScriptByDataTable(dt, strPrimaryKeyColumn, isIdentity);
sb_CurrentTableScript.AppendLine();
sb_AllTableScript.Append(sb_CurrentTableScript);
}
}
rtbSqlContent.Text = sb_AllTableScript.ToString();
}
/// <summary>
/// 用途:
/// 用源表和目标表比较,返回差异的数据(目标表为参照物)
///
/// 逻辑:
/// 1、合并两个表
/// 2、循环合并后得到的表,判断是否在目标表中存在,如果不存在,则是新增的,RowState为设置为ADD,如果存在,RowState设置为Modify
/// </summary>
/// <param name="sourceTable">源表</param>
/// <param name="targetTable">目标表</param>
/// <param name="primaryKeyColumn">主键字段</param>
/// <returns>差异数据的DataTable,该DataTable中必须有TableName属性,而且是跟数据库中的表一致的</returns>
private DataTable GetDataTableExceptData(DataTable sourceTable,DataTable targetTable,string tableName,string primaryKeyColumn)
{
DataTable dtExcept = new DataTable(sourceTable.TableName);
try
{
dtExcept = sourceTable.AsEnumerable().Except(targetTable.AsEnumerable(),DataRowComparer.Default).CopyToDataTable();
}
catch (Exception)
{
}
for (int i = 0; i < dtExcept.Rows.Count; i++)
{
object obj = dtExcept.Rows[i][primaryKeyColumn];
targetTable.DefaultView.Sort = primaryKeyColumn;
int count = targetTable.DefaultView.Find(obj);
if (count >= 0)
{
dtExcept.Rows[i].SetModified();
}else{
dtExcept.Rows[i].SetAdded();
}
}
dtExcept.TableName = tableName;
return dtExcept;
}
/// <summary>
/// 用途:
/// 根据DataTable 获取SQL脚本
///
/// 逻辑:
/// 1、先判断是否是自动曾长的,如果是自动增长,先关闭自动增长
/// </summary>
/// <param name="dt">源DataTable与目标DataTable的差异</param>
/// <param name="primaryKeyColumn">主键字段</param>
/// <param name="isIdentity">是否自动增长</param>
/// <returns>SQL脚本</returns>
private StringBuilder GetScriptByDataTable(DataTable dt, string primaryKeyColumn,bool isIdentity)
{
StringBuilder sb = new StringBuilder("");
// 开启自动增长时能进行插入数据,后面对应有关闭
if (isIdentity)
{
sb.AppendLine();
sb.Append("-- ===========================" + dt.TableName + "===============================");
sb.AppendLine();
sb.Append("SET IDENTITY_INSERT " + dt.TableName + " ON");
}
if (dt.TableName == "")
{
DialogResult result = MessageBox.Show("DataTable 的 TableName 未指定");
return null;
}
List<string> list_Column = new List<string>();
foreach (DataColumn item in dt.Columns)
{
list_Column.Add(item.ColumnName);
}
for (int i = 0; i < dt.Rows.Count; i++)
{
StringBuilder sb_Insert = new StringBuilder("");
DataRowState rowState = dt.Rows[i].RowState;
if (rowState == DataRowState.Added)
{
StringBuilder sb_Column = new StringBuilder();
StringBuilder sb_Values = new StringBuilder();
sb_Insert.AppendLine();
sb_Insert.Append("INSERT INTO " + dt.TableName + "(");
for (int m = 0; m < list_Column.Count; m++)
{
sb_Column.Append("," + list_Column[m]);
sb_Values.Append(",'" + dt.Rows[i][list_Column[m]]+"'");
}
sb_Insert.Append(sb_Column.ToString());
sb_Insert.Append(") VALUES(");
sb_Insert.Append(sb_Values.ToString());
sb_Insert.Append(");");
sb_Insert.Replace("INSERT INTO "+ dt.TableName +"(,", "INSERT INTO "+ dt.TableName +"(");
sb_Insert.Replace("VALUES(,", "VALUES(");
sb.Append(sb_Insert.ToString());
}
if (rowState == DataRowState.Modified)
{
StringBuilder sb_Update = new StringBuilder("");
sb_Update.AppendLine();
sb_Update.Append("UPDATE " + dt.TableName + " SET ");
for (int k = 0; k < list_Column.Count; k++)
{
if (list_Column[k] != primaryKeyColumn)
{
sb_Update.Append("," + list_Column[k] + "='" + dt.Rows[i][list_Column[k]] + "'");
}
}
sb_Update.Replace("SET ,", "SET ");
sb_Update.Append(" WHERE " + primaryKeyColumn + " = '" + dt.Rows[i][primaryKeyColumn] + "';");
sb.Append(sb_Update.ToString());
}
if (i > 0 && i % 100 == 0)
{
sb.AppendLine();
sb.Append("GO;");
sb.AppendLine();
}
}
// 关闭自动增长时能进行插入数据,前面对应有开启
if (isIdentity)
{
sb.AppendLine();
sb.Append("SET IDENTITY_INSERT " + dt.TableName + " OFF");
}
return sb;
}
/// <summary>
/// 需要同步的表
/// </summary>
/// <returns></returns>
private DataTable GetTableList()
{
DataTable dt = new DataTable();
DataRow row = null;
dt.Columns.AddRange(new DataColumn[]{
new DataColumn("TableName",typeof(string))
,new DataColumn("PrimaryKeyColumn",typeof(string))
,new DataColumn("IsIdentity",typeof(bool))
});
row = dt.NewRow();
row["TableName"] = "TB_A";
row["PrimaryKeyColumn"] = "Id";
row["IsIdentity"] = true;
dt.Rows.Add(row);
row = dt.NewRow();
row["TableName"] = "TB_B";
row["PrimaryKeyColumn"] = "Id";
row["IsIdentity"] = true;
dt.Rows.Add(row);
return dt;
}
// 表的同步
private void btnDbTransmisson_Click(object sender, EventArgs e)
{
}
}
}
两个数据库通过DataTable实现差异传输的更多相关文章
- 比较两个数据库表table结构不同之处
/*--比较两个数据库的表字段差异 hy 适用多种版本库 --*/ /*--调用示例 exec p_comparestructure 'database1','database2' --*/ ) dr ...
- ORACLE如何比较两个数据库的差异
ORACLE怎么比较两个数据库的差异 方法1:使用PL-SQL工具 点击 工具->比较用户对象
- 比较两个mysql数据库表结构的差异
需求来源:一个线上系统,一个开发系统,现在要把开发系统更新到线上,但是开发系统的数据库结构与线上的略有差异,所以需要找出两个数据库的表结构差异. 数据库表结构的差异 注:操作均在Linux系统下完成 ...
- SQL SERVER 比较两个数据库中表和字段的差异
在开发过程中线上的数据库表字段和本地数据库表字段是存在的,也许我们在本地数据库中所增加的表字段都会有记录到SQL文件中,但当增加的表及字段名称较多时总会出现漏网之鱼,发布真是版本的时候回出现很多很多的 ...
- 使用Red Gate Sql Compare 数据库同步工具进行SQL Server的两个数据库的结构比较、同步
将测试版的项目同步(部署)到正式版的时候,两个数据库的结构比较与同步时,如果修改数据库的时候没有记录好修改了那些表,很难将两个数据库进行同步 RedGate Sql Compare使用简介说明: 1. ...
- delphi 创建DBASE和FOXPRO两类DBF数据文件的差异
delphi 创建DBASE和FOXPRO两类DBF数据文件的差异,主要有几点: 1.创建方法不同 DBASE的创建方法: Self.Table1.Close; Self.Table1.Active ...
- sqlServer数据库备份与还原——差异备份与还原
1.差异备份 是完整备份的补充 备份自上次完整备份以来的数据变动的部分 2.备份过程: 在做差异备份之前需要先进行完整备份.完整备份的过程见:https://i.cnblogs.com/EditPos ...
- 固态硬盘和机械硬盘的比较和SQLSERVER在两种硬盘上的性能差异
固态硬盘和机械硬盘的比较和SQLSERVER在两种硬盘上的性能差异 在看这篇文章之前可以先看一下下面的文章: SSD小白用户收货!SSD的误区如何解决 这样配会损失性能?实测6种特殊装机方式 听说固态 ...
- 使用mysqldiff生成两个数据库结构不同的脚本
1,全库比较各个表的不同,并输出到文件 mysqldiff --server1=root:root@localhost --server2=root:root@localhost --difftype ...
随机推荐
- js语法和数据类型
基础知识(Basics) JavaScript 的很多语法借鉴自 Java,但也受 Awk,Perl 和 Python 影响. JavaScript 是大小写敏感的,使用 Unicode 字符集. 在 ...
- CF 671D Roads in Yusland
弄完之后点进去一看,竟然是div1的D题……最近真是天天被题虐哭 推荐这一篇博客 https://www.cnblogs.com/Sakits/p/8085598.html 感觉讲清楚了,也是基本照着 ...
- Git 之 github分享代码
作为一个技术人员还是脱离不了屌丝的本质,所以每天都是逛逛github,看看别人有什么好的项目,自己可以给他挑挑bug也可以提供自己的水平,但是别人不那怎么才能给别人贡献代码呢?那就是fork了.... ...
- Oracle数据库之多表查询一
上一篇给大家介绍了数据的单表查询,相信大家对于单表的查询应该都有了一些了解.单表查询在数据库中的使用会有一些,但并不是很多,但是作为初学者,我们需要学习单表查询的思路.今天呢,我们为大家介绍一下数据库 ...
- C++面试笔记--字符串
基本上求职者进行笔试没有不考字符串的.字符串也是一种相对简单的数据结构,容易被考.事实上,字符创也是一个考验程序猿编程规范和编程习惯的重要考点. 1.替换空格:实现一个函数,把字符串中的每个空格替换成 ...
- JaVA web服务器配置
1:第一是下载好Eclipse开发工具,这里不做叙述,自行下载安装. 2:使用Eclipse开发WEB项目,启动Eclipse,选择File--->new --->other---> ...
- 通过shell脚本开始和结束守护进程
//关闭脚本 #!/bin/sh WHOAMI=`whoami` PID=`ps -u $WHOAMI | grep 守护进程名 | awk '{print $1}'` if (用户名 "$ ...
- Spring Boot 学习系列(02)—使用热部署,提升开发效
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...
- Nginx部署静态页面及引用图片有效访问的两种方式
nginx安装百度一下有很多,直接正题: 静态文件目录结构 file#文件位置 /home/service/file/ css js images html fonts 配置nginx.conf核心代 ...
- 算法训练 数字三角形(DP)
问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每一步可沿左斜线向下或右斜线向下走: ●1<三角形行数≤100: ...