zoukankan      html  css  js  c++  java
  • 两个数据库通过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)
    {

    }
    }
    }

  • 相关阅读:
    ajax的原理及实现方式
    在linux中添加环境变量
    ftp简单命令
    linux命令之scp
    java中创建对象的方法
    10个调试技巧
    java读取.properties配置文件的几种方法
    Java对象和XML转换
    Java Float类型 减法运算时精度丢失问题
    Java内存分配全面浅析
  • 原文地址:https://www.cnblogs.com/chengeng/p/7505475.html
Copyright © 2011-2022 走看看