You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

459 lines
17 KiB

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<string> m_LogsTemp = new List<string>();
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<string> m_Logs = new List<string>();
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<string, List<string>> m_Tables = new Dictionary<string, List<string>>();
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<string>
{
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<string> tabels = new List<string>();
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<int, string> dic = new Dictionary<int, string>();
//添加字段
//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<DBExportConf>(File.ReadAllText(fname));
}
catch { }
}
#endregion
}
#region 配置项
public class Content
{
/// <summary>
///
/// </summary>
public List<string> All { get; set; }
/// <summary>
///
/// </summary>
public List<string> Except { get; set; }
/// <summary>
///
/// </summary>
public List<string> Limit { get; set; }
}
public class DBExportConf
{
/// <summary>
///
/// </summary>
public Content Content { get; set; }
/// <summary>
///
/// </summary>
public int LimitTime { get; set; }
}
#endregion
}