123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- using Dapper;
- using SharpCompress.Archives;
- using SharpCompress.Common;
- using SharpCompress.Writers;
- using System;
- using System.Data;
- using System.IO;
- using System.Text.RegularExpressions;
- using Vit.Core.Module.Log;
- using Vit.Extensions;
- using Vit.Orm.Dapper;
- namespace Vit.Db.DbMng
- {
- public abstract class BaseDbMng<DbConnection>
- where DbConnection : IDbConnection
- {
- protected DbConnection conn;
- public BaseDbMng(DbConnection conn)
- {
- this.conn = conn;
- }
- /// <summary>
- /// 获取数据库状态
- /// </summary>
- /// <returns></returns>
- public abstract EDataBaseState GetDataBaseState();
-
- /// <summary>
- /// 创建数据库
- /// </summary>
- public abstract void CreateDataBase();
-
- /// <summary>
- /// 删除数据库
- /// </summary>
- public abstract void DropDataBase();
- /// <summary>
- /// 数据库是否存在
- /// </summary>
- /// <returns></returns>
- public virtual bool DataBaseIsOnline()
- {
- return GetDataBaseState() == EDataBaseState.online;
- }
- /// <summary>
- /// 构建建库语句
- /// </summary>
- /// <returns></returns>
- public abstract string BuildCreateDataBaseSql();
- protected abstract string Quote(string name);
- #region BackupSqler
- /// <summary>
- /// 备份数据库
- /// </summary>
- /// <param name="filePath">备份的文件路径。demo:@"F:\\website\appdata\dbname_2020-02-02_121212.bak"</param>
- /// <returns>备份的文件路径</returns>
- public virtual string BackupSqler(string filePath)
- {
- var tempPath = filePath + "_Temp";
- try
- {
- //(x.1)创建临时文件夹
- Directory.CreateDirectory(tempPath);
- #region (x.2)构建备份文件
- #region (x.x.1)创建建库语句文件(CreateDataBase.sql)
- var sqlPath = Path.Combine(tempPath, "CreateDataBase.sql");
- var sqlText = BuildCreateDataBaseSql();
- File.WriteAllText(sqlPath, sqlText, System.Text.Encoding.GetEncoding("utf-8"));
- #endregion
- #region (x.x.2)获取所有表数据(Data.sqlite3)
- string sqlitePath = Path.Combine(tempPath, "Data.sqlite3");
- #region backup to sqlite
- //using (var conn = ConnectionFactory.MySql_GetOpenConnection(sqlConnectionString))
- using (var connSqlite = ConnectionFactory.Sqlite_GetOpenConnectionByFilePath(sqlitePath))
- {
- //Logger.Info(" mysql backup");
- //Logger.Info(" backup database " + conn.Database);
- var tableNames = conn.GetAllTableName();
- int tbCount = 0;
- int sumRowCount = 0;
- foreach (var tableName in tableNames)
- {
- tbCount++;
- //try
- //{
- //Logger.Info($" [{tbCount}/{tableNames.Count}]start backup table " + tableName);
-
- int rowCount;
- using (IDataReader dr = conn.ExecuteReader($"select * from {Quote(tableName)}"))
- {
- //(x.x.1)create table
- //Logger.Info(" [x.x.1]create table " + tableName);
- connSqlite.Sqlite_CreateTable(dr, tableName);
- //(x.x.2)import table
- //Logger.Info(" [x.x.2]import table " + tableName + " start...");
- rowCount = connSqlite.Import(dr, tableName);
- }
- sumRowCount += rowCount;
- //Logger.Info(" import table " + tableName + " success,row count:" + rowCount);
- //}
- //catch (Exception ex)
- //{
- // Logger.Error(ex);
- //}
- }
- //var span = (DateTime.Now - startTime);
- //Logger.Info(" mysql backup success,sum row count:" + sumRowCount + $",耗时:{span.Hours}小时{span.Minutes}分{span.Seconds}秒{span.Milliseconds}毫秒");
- }
- #endregion
- #endregion
- #endregion
- #region (x.3)压缩备份文件
- //待压缩文件夹
- string input = tempPath;
- //压缩后文件名
- string output = filePath;
- var archiveType = ArchiveType.Zip;
- var compressionType = SharpCompress.Common.CompressionType.Deflate;
- var writerOptions = new WriterOptions(compressionType);
- writerOptions.ArchiveEncoding.Default = System.Text.Encoding.GetEncoding("utf-8");
- using (var fileStream = File.OpenWrite(output))
- using (var writer = WriterFactory.Open(fileStream, archiveType, writerOptions))
- {
- writer.WriteAll(input, "*", SearchOption.AllDirectories);
- }
- #endregion
- }
- finally
- {
- Directory.Delete(tempPath, true);
- }
- return filePath;
- }
- #endregion
- #region RestoreSqler
- protected virtual Regex RestoreSqler_SqlSplit => null;
-
- /// <summary>
- /// 远程还原数据库
- /// </summary>
- /// <param name="filePath">数据库备份文件的路径</param>
- /// <returns>备份文件的路径</returns>
- public virtual string RestoreSqler(string filePath)
- {
- var tempPath = filePath + "_Temp";
- try
- {
- //(x.1)创建临时文件夹
- Directory.CreateDirectory(tempPath);
- #region (x.1)解压备份文件到临时文件夹
- //待解压文件
- var input = filePath;
- var output = tempPath;
- using (var archive = ArchiveFactory.Open(input))
- {
- foreach (var entry in archive.Entries)
- {
- entry.WriteToDirectory(output, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
- }
- }
- #endregion
- #region (x.2)还原数据库
- //(x.x.1)若数据库存在,则删除数据库
- if (DataBaseIsOnline()) DropDataBase();
- //创建数据库
- CreateDataBase();
- #region (x.x.2)创建建库语句文件(CreateDataBase.sql)
- var sqlPath = Path.Combine(tempPath, "CreateDataBase.sql");
- var sqlText = File.ReadAllText(sqlPath, System.Text.Encoding.GetEncoding("utf-8"));
- Action runSql = () => {
- using (var tran = conn.BeginTransaction())
- {
- try
- {
- int index = 1;
-
-
- Regex reg = RestoreSqler_SqlSplit;
- if (reg == null)
- {
- conn.Execute(sqlText, transaction: tran);
- }
- else
- {
- var sqls = reg.Split(sqlText);
- foreach (String sql in sqls)
- {
- if (String.IsNullOrEmpty(sql.Trim()))
- {
- //sendMsg(EMsgType.Title, $"[{(index++)}/{sqls.Length}]空语句,无需执行.");
- }
- else
- {
- conn.Execute(sql,transaction: tran);
- //sendMsg(EMsgType.Title, $"[{(index++)}/{sqls.Length}]执行sql语句:");
- //sendMsg(EMsgType.Nomal, sql);
- //var result = "执行结果:" + conn.Execute(sql, null, tran) + " Lines effected.";
- //sendMsg(EMsgType.Title, result);
- }
- }
- }
- tran.Commit();
- }
- catch (Exception ex)
- {
- Logger.Error(ex);
- tran.Rollback();
- throw;
- }
- }
- };
- //确保conn打开
- if (conn.State == ConnectionState.Open)
- {
- runSql();
- }
- else
- {
- try
- {
- conn.Open();
- runSql();
- }
- finally
- {
- conn.Close();
- }
- }
- #endregion
- #region (x.x.3)导入所有表数据(Data.sqlite3)
- string sqlitePath = Path.Combine(tempPath, "Data.sqlite3");
-
- //using (var conn = ConnectionFactory.MySql_GetOpenConnection(sqlConnectionString))
- using (var connSqlite = ConnectionFactory.Sqlite_GetOpenConnectionByFilePath(sqlitePath))
- {
- var tableNames = connSqlite.Sqlite_GetAllTableName();
- int tbCount = 0;
- int sumRowCount = 0;
- foreach (var tableName in tableNames)
- {
- tbCount++;
- //Logger.Info($" [{tbCount}/{tableNames.Count}]start import table " + tableName);
- //get data
- using (var dr = connSqlite.ExecuteReader($"select * from {connSqlite.Quote(tableName)}"))
- {
- //(x.4)
- //Logger.Info(" [x.x.4]import table " + dt.TableName + ",row count:" + dt.Rows.Count);
- var rowCount = conn.BulkImport(dr, tableName);
- sumRowCount += rowCount;
- //Logger.Info(" import table " + dt.TableName + " success");
- }
- }
- //var span = (DateTime.Now - startTime);
- //Logger.Info(" mysql import success,sum row count:" + sumRowCount + $",耗时:{span.Hours}小时{span.Minutes}分{span.Seconds}秒{span.Milliseconds}毫秒");
- }
- #endregion
- #endregion
- }
- finally
- {
- Directory.Delete(tempPath, true);
- }
- return filePath;
- }
- #endregion
- }
- }
|