using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Data; using System.Text; using System.Windows.Forms; using System.IO; namespace Tiobon.Core.OPS.Tool.OPS.Tool.View { public partial class Frm_DbExport : Form { #region 初始化 string m_ConnStr = ""; public Frm_DbExport(string connStr) { InitializeComponent(); m_ConnStr = connStr; LoadTables(); LoadConf(); } private void Form_DbExport_Load(object sender, EventArgs e) { timer_Main.Start(); } #endregion #region 选择文件路径 string m_FileName = ""; private void btn_select_Click(object sender, EventArgs e) { using (FolderBrowserDialog path = new FolderBrowserDialog()) { if (path.ShowDialog() == DialogResult.OK) { if (System.IO.File.Exists($"{ path.SelectedPath}\\hdis_{DateTime.Now.ToString("yyyy_MM_dd")}.sql")) { if (MessageBox.Show("文件已存在,是否覆盖?", "警告", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) { return; } } this.txt_fname.Text = $"{ path.SelectedPath}\\hdis_{DateTime.Now.ToString("yyyy_MM_dd")}.sql";//返回文件的完整路径 } } } #endregion #region 日志操作 private static List m_LogsTemp = new List(); private void timer_Main_Tick(object sender, EventArgs e) { try { lock (m_Logs) { m_LogsTemp.Clear(); m_Logs.ForEach(log => m_LogsTemp.Add(log)); m_Logs.Clear(); } if (m_LogsTemp.Count > 0) { if (this.lb_Logger.Items.Count > 2000) this.lb_Logger.Items.Clear(); m_LogsTemp.ForEach(log => this.lb_Logger.Items.Add(log)); this.lb_Logger.TopIndex = this.lb_Logger.Items.Count - 1; } } catch { } } private static List m_Logs = new List(); private void SendLog(string oprator, string msg) { lock (m_Logs) { if (string.IsNullOrEmpty(oprator)) m_Logs.Add($"{DateTime.Now.ToString("HH:mm:ss")} {msg}"); else m_Logs.Add($"{DateTime.Now.ToString("HH:mm:ss")} [{oprator}] {msg}"); } } #endregion #region 加载表名 Dictionary> m_Tables = new Dictionary>(); private void LoadTables() { try { m_Tables.Clear(); string sql = $"SELECT * FROM INFORMATION_SCHEMA.`COLUMNS` C WHERE C.TABLE_SCHEMA = 'hdis';"; DataTable dt = MySqlHelper.ExecuteDataset(m_ConnStr, sql).Tables[0]; foreach (DataRow dr in dt.Rows) { if (!m_Tables.ContainsKey(dr["TABLE_NAME"].ToString())) { m_Tables.Add(dr["TABLE_NAME"].ToString(), new List { dr["COLUMN_NAME"].ToString() }); treeView_Main.Nodes[0].Nodes.Add(dr["TABLE_NAME"].ToString()); } else { m_Tables[dr["TABLE_NAME"].ToString()].Add(dr["COLUMN_NAME"].ToString()); } } treeView_Main.ExpandAll(); foreach (TreeNode node in treeView_Main.Nodes[0].Nodes) { node.Checked = true; } } catch (Exception ex) { MessageBox.Show("读取数据库结构失败:" + ex.Message); } } #endregion #region 选中节点 private void treeView_Main_BeforeCheck(object sender, TreeViewCancelEventArgs e) { TreeViewCheck.CheckControl(e); } #endregion #region 导出 List tabels = new List(); private void btn_Export_Click(object sender, EventArgs e) { m_FileName = this.txt_fname.Text; if (m_FileName == "") return; if (b_In) { return; } tabels.Clear(); foreach (TreeNode node in treeView_Main.Nodes[0].Nodes) { if (node.Checked) { tabels.Add(node.Text); } } if (tabels.Count > 0) { System.Threading.Thread th = new System.Threading.Thread(Export); th.Start(); } } bool b_In = false; object m_Lock = new object(); private void Export() { lock (m_Lock) { if (b_In) { return; } else { b_In = true; } } DateTime dtStart = DateTime.Now; try { SendLog("", "共有表 " + tabels.Count); if (File.Exists(m_FileName)) { File.Delete(m_FileName); } int tcount = 0; StringBuilder sb = new StringBuilder(); sb.AppendLine("SET FOREIGN_KEY_CHECKS = 0;"); tabels.ForEach(tabelname => { SetTotal(tabels.Count, ++tcount); sb.AppendLine($"-- 正在导出 表 hdis.{tabelname} 结构"); SendLog("", $"-- 正在导出 表 hdis.{tabelname} 结构"); //删除原表 //sb.AppendLine($"DROP TABLE IF EXISTS `{tabelname}`;"); //导出表结构 sb.AppendLine($"{MySqlHelper.ExecuteDataset(m_ConnStr, $"SHOW CREATE TABLE `hdis`.`{tabelname}`;").Tables[0].Rows[0]["Create Table"].ToString()};"); sb.AppendLine(); //判断配置 string strWhere = string.Empty; if (m_DBExportConf != null && m_DBExportConf.Content != null) { if (m_DBExportConf.Content.Except != null && !m_DBExportConf.Content.Except.Contains(tabelname) && m_DBExportConf.Content.Limit != null && !m_DBExportConf.Content.Limit.Contains(tabelname) && m_DBExportConf.Content.All != null && !m_DBExportConf.Content.All.Contains(tabelname)) { //只导出表结构不导出数据 WriteToFile($"{sb.ToString()}"); sb.Clear(); SendLog("", $"表 {tabelname} [未配置] 只导出结构不导出数据"); return; } if (m_DBExportConf.Content.Except != null && m_DBExportConf.Content.Except.Contains(tabelname)) { //只导出表结构不导出数据 WriteToFile($"{sb.ToString()}"); sb.Clear(); SendLog("", $"表 {tabelname} 只导出结构不导出数据"); return; } if (m_DBExportConf.Content.Limit != null && m_DBExportConf.Content.Limit.Contains(tabelname)) { //导出规定时间内的数据,包含create_time字段 if (m_Tables[tabelname].Contains("create_time")) { SendLog("", $"表 {tabelname} 只导出 {m_DBExportConf.LimitTime} 天以内的数据"); strWhere = $" where create_time >= '{DateTime.Now.AddDays(m_DBExportConf.LimitTime * -1).ToString("yyyy-MM-dd HH:mm:ss")}'"; } } } //导出数据 sb.AppendLine($"-- 正在导出 表 hdis.{tabelname} 数据"); int rows = int.Parse(MySqlHelper.ExecuteScalar(m_ConnStr, $"SELECT COUNT(0) FROM `hdis`.`{tabelname}`{strWhere};").ToString()); SendLog("", $"-- 正在导出 表 hdis.{tabelname} 数据,共有数据 {rows}"); int sum = 0; using (MySqlDataReader reader = MySqlHelper.ExecuteReader(m_ConnStr, $"SELECT * FROM `hdis`.`{tabelname}`{strWhere};")) { if (reader.HasRows) { //字段类型 Dictionary dic = new Dictionary(); //添加字段 //sb.AppendLine($"DELETE FROM `{tabelname}`;"); StringBuilder sb_insert = new StringBuilder(); sb_insert.Append($"INSERT INTO `{tabelname}` ("); for (int i = 0; i < reader.FieldCount; ++i) { sb_insert.Append($"`{reader.GetName(i)}`"); if (i != reader.FieldCount - 1) sb_insert.Append(", "); dic.Add(i, reader.GetDataTypeName(i)); } sb_insert.Append(") VALUES"); sb_insert.AppendLine(); //表开始 WriteToFile($"{sb.ToString()}"); sb.Clear(); int index = 0; //添加数据 while (reader.Read()) { sum++; sb.Append("\t("); for (int i = 0; i < reader.FieldCount; ++i) { sb.Append($"{ConvertData(reader[i], dic[i])}"); if (i != reader.FieldCount - 1) sb.Append(", "); } sb.Append(")"); //500行数据入库一次 if (index++ >= 500) { sb.Append(";"); sb.AppendLine(); sb.AppendLine(); WriteToFile($"{sb_insert.ToString()}{sb.ToString()}"); sb.Clear(); index = 0; continue; } //1024KB为一组插入语句 if (sb.Length >= 100 * 1024) { sb.Append(";"); sb.AppendLine(); sb.AppendLine(); WriteToFile($"{sb_insert.ToString()}{sb.ToString()}"); sb.Clear(); index = 0; continue; } if (sum != rows) sb.Append(","); else sb.Append(";"); sb.AppendLine(); } //表结束 if (sb.Length > 0) { sb.AppendLine(); WriteToFile($"{sb_insert.ToString()}{sb.ToString()}"); sb.Clear(); index = 0; } } } sb.AppendLine(); }); sb.AppendLine("SET FOREIGN_KEY_CHECKS = 1;"); if (sb.Length > 0) WriteToFile(sb.ToString()); DateTime dtEnd = DateTime.Now; SendLog("", $"导出数据完毕,耗时 {(int)((dtEnd - dtStart).TotalSeconds / 60)}:{(int)((dtEnd - dtStart).TotalSeconds % 60)}"); } catch (Exception ex) { SendLog("", "导出数据异常" + ex.ToString()); } finally { lock (m_Lock) { b_In = false; } } } private string ConvertData(object data, string type) { if (data.GetType().FullName == "System.DBNull") return "NULL"; string value; switch (type) { case "VARCHAR": { value = data.ToString(); if (value.IndexOf("\r") > 0) value = value.Replace("\r", "\\r"); if (value.IndexOf("\n") > 0) value = value.Replace("\n", "\\n"); if (value.IndexOf("'") > 0) value = value.Replace("'", "''"); if (value.IndexOf("\\") > 0) value = value.Replace("\\", "\\\\"); value = $"'{value}'"; break; } case "JSON": { value = data.ToString().Trim() == "" ? "NULL" : $"'{data.ToString()}'"; break; } case "TIMESTAMP": value = data.ToString().Trim() == "" ? "NULL" : $"'{Convert.ToDateTime(data.ToString()).ToString("yyyy-MM-dd HH:mm:ss")}'"; break; case "DATE": value = data.ToString().Trim() == "" ? "NULL" : $"'{Convert.ToDateTime(data.ToString()).ToString("yyyy-MM-dd")}'"; break; default: value = data.ToString().Trim() == "" ? "NULL" : data.ToString(); break; } return value; } private void WriteToFile(string content) { if (!File.Exists(m_FileName)) { using (StreamWriter sw = File.CreateText(m_FileName)) { sw.Write(content); } } else { using (StreamWriter sw = File.AppendText(m_FileName)) { sw.Write(content); } } } #endregion #region 进度 private void SetTotal(int max, int value) { try { this.BeginInvoke(new EventHandler(delegate { progressBar_Main.Minimum = 0; progressBar_Main.Maximum = max; progressBar_Main.Value = value; lbl_pro.Text = $"{value}/{max}"; })); } catch { } } #endregion #region 加载配置项 DBExportConf m_DBExportConf; private void LoadConf() { try { string fname = AppDomain.CurrentDomain.BaseDirectory + @"\Config\DBExportConfig.json"; if (File.Exists(fname)) m_DBExportConf = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(fname)); } catch { } } #endregion } #region 配置项 public class Content { /// /// /// public List All { get; set; } /// /// /// public List Except { get; set; } /// /// /// public List Limit { get; set; } } public class DBExportConf { /// /// /// public Content Content { get; set; } /// /// /// public int LimitTime { get; set; } } #endregion }