using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Dapper; using Repository.Helper; using Repository.Models; using Repository.BaseRepository.Interface; using System.Reflection; using System.Data; using System.Text; using System.Data.SqlClient; using MySql.Data.MySqlClient; using Repository.Services.Implement; namespace Repository.BaseRepository.Implement { public class BaseRepository : IBaseRepository { protected readonly IDatabaseHelper _databaseHelper; protected string UseDB; protected IDbConnection con; private BackgroundService backgroundService; //排除要加入至派送的資料表 private List<string> exclude_data_delivery = new List<string>() { "background_service_message_notification_task", "background_service_message_notification_task_log", "background_service_plan", "background_service_task", "background_service_task_log", "device_import_temp", "device_import_ckeck_temp", "operation_back_log", "operation_log", "task_detail", "api_earthquake", "api_rain", "api_sync", "api_typhoon", "api_weateher", "archive_electric_meter_day", "archive_electric_meter_hour", "archive_electric_meter_month", "archive_electric_meter_week" }; public BaseRepository(IDatabaseHelper databaseHelper) { this._databaseHelper = databaseHelper; } public IDbConnection GetDbConnection() { IDbConnection conn; if (UseDB == "MSSQL") { conn = new SqlConnection(this._databaseHelper.GetMSSqlConnectionString()); } else { conn = new MySqlConnection(this._databaseHelper.GetMySqlConnectionString()); } return conn; } public string InsertGenerateString(List<string> properties, string table_name) { var insertQuery = new StringBuilder($"INSERT INTO {table_name} "); insertQuery.Append("("); properties.ForEach(prop => { insertQuery.Append($"{table_name}.{prop.Replace("@", "")},"); }); insertQuery .Remove(insertQuery.Length - 1, 1) .Append(") VALUES ("); properties.ForEach(prop => { insertQuery.Append($"{prop},"); }); insertQuery .Remove(insertQuery.Length - 1, 1) .Append(");"); return insertQuery.ToString(); } public string UpdateGenerateString(List<string> properties, string table_name, string sWhere) { var updateQuery = new StringBuilder($"UPDATE {table_name} SET "); properties.ForEach(property => { if (property.Contains("@")) { updateQuery.Append($"{property.Replace("@", "")}={property},"); } }); updateQuery.Remove(updateQuery.Length - 1, 1); //remove last comma updateQuery.Append($" WHERE {sWhere}"); return updateQuery.ToString(); } #region GetAll /// <summary> /// 取得所有資料(根據條件以及排序) /// </summary> /// <typeparam name="A"></typeparam> /// <param name="tableName"></param> /// <param name="sWhere"></param> /// <param name="param">Ex: new { status = 1}</param> /// <returns></returns> public virtual async Task<List<A>> GetAllAsync<A>(string tableName, string sWhere, object param = null, string sOrderBy = "") { List<A> result; using (IDbConnection conn = GetDbConnection()) { try { var sql = $"SELECT * FROM {tableName}"; if (!string.IsNullOrEmpty(sWhere)) { sql += $" WHERE {sWhere}"; } if (!string.IsNullOrEmpty(sOrderBy)) { sql += $" ORDER BY {sOrderBy}"; } result = (await conn.QueryAsync<A>(sql, param)).ToList(); } catch (Exception exception) { throw exception; } return result; } } /// <summary> /// 根據SQL語句抓取整包資料 /// </summary> /// <typeparam name="A"></typeparam> /// <param name="sqlString"></param> /// <returns></returns> public virtual async Task<List<A>> GetAllAsync<A>(string sqlString, object param = null) { List<A> result; using (IDbConnection conn = GetDbConnection()) { try { var sql = sqlString; result = (await conn.QueryAsync<A>(sql, param)).ToList(); } catch (Exception exception) { throw exception; } return result; } } /// <summary> /// 取得多筆資料的某個欄位變成列表 /// </summary> /// <param name="guid">流水號</param> /// <param name="table_name">資料表名稱</param> /// <param name="idName">指定欄位名稱的流水號</param> /// <param name="selCol">選擇陣列資料庫欄位名稱</param> /// <returns></returns> public virtual async Task<List<object>> GetAllWithCustomDBNameAndTableAsync(string guid, string table_name, string idName, string selCol) { List<object> result; using (IDbConnection conn = GetDbConnection()) { try { var sql = $"SELECT {selCol} FROM {table_name} WHERE {idName} = @Guid"; result = (await conn.QueryAsync<object>(sql, new { Guid = guid })).ToList(); } catch (Exception exception) { throw exception; } return result; } } #endregion GetAll #region GetOne /// <summary> /// 取得單一筆資料(排序) /// </summary> /// <typeparam name="A"></typeparam> /// <param name="tableName"></param> /// <param name="sWhere"></param> /// <param name="param">參數值</param> /// <param name="sOrderBy"></param> /// <returns></returns> public virtual async Task<A> GetOneAsync<A>(string tableName, string sWhere, object param = null, string sOrderBy = "") { A result; using (IDbConnection conn = GetDbConnection()) { try { var sql = $"SELECT * FROM {tableName}"; if (!string.IsNullOrEmpty(sWhere)) { sql += $" WHERE {sWhere}"; } if (!string.IsNullOrEmpty(sOrderBy)) { sql += $" ORDER BY {sOrderBy}"; } result = await conn.QueryFirstOrDefaultAsync<A>(sql, param); } catch (Exception exception) { throw exception; } return result; } } /// <summary> /// 取得單一筆資料某一欄位(排序) /// </summary> /// <param name="tableName"></param> /// <param name="sWhere"></param> /// <param name="selCol">填放欄位</param> /// <param name="param">參數值</param> /// <param name="sOrderBy"></param> /// <returns></returns> public virtual async Task<object> GetOneAsync(string tableName, string sWhere, string selCol, object param = null, string sOrderBy = "") { object result; using (IDbConnection conn = GetDbConnection()) { try { var sql = $"SELECT {selCol} FROM {tableName}"; if (!string.IsNullOrEmpty(sWhere)) { sql += $" WHERE {sWhere}"; } if (!string.IsNullOrEmpty(sOrderBy)) { sql += $" ORDER BY {sOrderBy}"; } result = await conn.QueryFirstOrDefaultAsync<object>(sql, param); } catch (Exception exception) { throw exception; } return result; } } /// <summary> /// 取得單一筆資料(根據自訂SQL, 自訂參數) /// </summary> /// <param name="sqlString"></param> /// <param name="param"></param> /// <returns></returns> public virtual async Task<A> GetOneAsync<A>(string sqlString, object param = null) { A result; using (IDbConnection conn = GetDbConnection()) { try { var sql = sqlString; result = await conn.QueryFirstOrDefaultAsync<A>(sql, param); } catch (Exception exception) { throw exception; } return result; } } #endregion GetOne #region DeleteOne (軟刪除) /// <summary> /// 透過guid,軟刪除單一筆資料 /// UPDATE {tableName} SET deleted = 1 WHERE {idName} = @Guid /// </summary> /// <param name="guid"></param> /// <returns></returns> public virtual async Task DeleteOne(string guid, string tableName, string idName) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { var sql = $"UPDATE {tableName} SET deleted = 1 WHERE {idName} = @Guid"; if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(tableName)) { Dictionary<string, object> dict = new Dictionary<string, object>() { { idName, guid}, { "@deleted", 1}, }; backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", tableName, "delete", dict, null, guid); } await conn.ExecuteAsync(sql, new { Guid = guid }, trans); trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } /// <summary> /// 透過guid、db_name、table_name,刪除指定的資料庫之資料表的一筆資料 /// </summary> /// <param name="guid"></param> /// <param name="db_name"></param> /// <param name="table_name"></param> /// <returns></returns> public virtual async Task DeleteOneByGuidWithCustomDBNameAndTable(string guid, string db_name, string table_name, string idName) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { var sql = $"UPDATE {db_name}.{table_name} SET Deleted = 1 WHERE {idName} = @Guid"; if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(table_name)) { Dictionary<string, object> dict = new Dictionary<string, object>() { { idName, guid}, { "@deleted", 1}, }; backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", $"{db_name}.{table_name}", "delete", dict, null, guid); } await conn.ExecuteAsync(sql, new { Guid = guid }, trans); trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion DeleteOne (軟刪除) #region PurgeOne (硬刪除) /// <summary> /// 根據Where條件進行刪除 /// </summary> /// <param name="table_name"></param> /// <param name="sWhere"></param> /// <returns></returns> public virtual async Task PurgeOneByGuidWithCustomDBNameAndTable(string table_name, string sWhere) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { var sql = $"DELETE FROM {table_name} WHERE {sWhere}"; if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(table_name)) { Dictionary<string, object> dict = new Dictionary<string, object>(); //判斷是否有and的情況 var swhere_splits_and = sWhere.Split("and"); foreach (var sWhere_and in swhere_splits_and) { var swhere_split = sWhere_and.Split('='); if (swhere_split.Length > 0) { dict.Add(swhere_split[0].Trim(), swhere_split[1].Replace("'", "").Trim()); } } backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", table_name, "purge", dict); } await conn.ExecuteAsync(sql, null, trans); trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } /// <summary> /// 指定單一欄位,實際刪除單一筆資料 /// </summary> /// <param name="guid"></param> /// <param name="table_name"></param> /// <param name="idName"></param> /// <returns></returns> public virtual async Task PurgeOneAsync(string guid, string table_name, string idName) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { var sql = $"DELETE FROM {table_name} WHERE {idName} = @Guid"; if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(table_name)) { Dictionary<string, object> dict = new Dictionary<string, object>() { { idName, guid}, }; backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", table_name, "purge", dict, null, guid); } await conn.ExecuteAsync(sql, new { Guid = guid }, trans); trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion PurgeOne (硬刪除) #region AddMuti /// <summary> /// 新增Table多筆資料 /// </summary> /// <param name="dict"></param> /// <param name="Table_name"></param> /// <returns></returns> public async Task AddMutiByCustomTable(List<Dictionary<string, object>> dict, string Table_name) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { List<string> properties = dict[0].Keys.ToList(); string sql = InsertGenerateString(properties, Table_name); await conn.ExecuteAsync(sql, dict, trans); if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(Table_name)) { backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", Table_name, "insert_list", dict); } trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion AddMuti #region AddOne /// <summary> /// 新增table一筆資料 /// </summary> /// <param name="dict">新增資料庫名稱以及值</param> /// <param name="Table_name">資料表名稱</param> /// <returns></returns> public async Task AddOneByCustomTable(Dictionary<string, object> dict, string Table_name) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { List<string> properties = dict.Keys.ToList(); string sql = InsertGenerateString(properties, Table_name); await conn.ExecuteAsync(sql, dict, trans); if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(Table_name)) { backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", Table_name, "insert", dict); } trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion AddOne #region UpdateOne /// <summary> /// 更新Table一筆資料 /// </summary> /// <param name="dict">更新資料庫名稱以及值</param> /// <param name="Table_name">資料表名稱</param> /// <param name="sWhere">Where條件</param> /// <returns></returns> public async Task UpdateOneByCustomTable(Dictionary<string, object> dict, string Table_name, string sWhere) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { List<string> properties = dict.Keys.ToList(); string sql = UpdateGenerateString(properties, Table_name, sWhere); await conn.ExecuteAsync(sql, dict, trans); if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(Table_name)) { //判斷是否有and的情況 var swhere_splits_and = sWhere.Split("and"); foreach(var sWhere_and in swhere_splits_and) { var swhere_split = sWhere_and.Split('='); if (swhere_split.Length > 0) { dict.Add(swhere_split[0].Trim(), swhere_split[1].Replace("'", "").Trim()); } } backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", Table_name, "update", dict); } trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion UpdateOne #region UpdateList /// <summary> /// 更新Table多筆筆資料 /// </summary> /// <param name="dict">更新資料庫名稱以及值</param> /// <param name="Table_name">資料表名稱</param> /// <param name="sWhere">Where條件</param> /// <returns></returns> public async Task UpdateListByCustomTable(List<Dictionary<string, object>> dicts, string Table_name, string sWhere) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { List<string> properties = dicts.First().Keys.ToList(); string sql = UpdateGenerateString(properties, Table_name, sWhere); await conn.ExecuteAsync(sql, dicts, trans); if (UseDB == "MSSQL" && !exclude_data_delivery.Contains(Table_name)) { backgroundService = new BackgroundService(conn, trans); await backgroundService.AddTask("", "", Table_name, "update_list", dicts); } trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } } #endregion UpdateList /// <summary> /// 取資料庫當前流水號 /// </summary> /// <param name="Table_name"></param> /// <param name="where"></param> /// <returns></returns> public async Task<string> GetCurrentSerialNumber(string Table_name, string where = "") { string Num; using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { var sql = @$"SELECT SerialNumber FROM {Table_name}"; if (!string.IsNullOrEmpty(where)) { sql += $" WHERE {where}"; } sql += " ORDER BY SerialNumber DESC"; Num = await conn.QueryFirstOrDefaultAsync<string>(sql); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } return Num; } /// <summary> /// 取資料表當前優先序 /// <para>SELECT Priority FROM {Table_name} WHERE {where} ORDER BY Priority DESC</para> /// </summary> /// <param name="Table_name"></param> /// <param name="where"></param> /// <returns></returns> public async Task<int> GetCurrentPriority(string Table_name, string where = "") { int Num = 0; using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { var sql = @$"SELECT Priority FROM {Table_name}"; if (!string.IsNullOrEmpty(where)) { sql += $" WHERE {where}"; } sql += " ORDER BY Priority DESC"; Num = await conn.QueryFirstOrDefaultAsync<int>(sql); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } return Num; } /// <summary> /// 透過id來搜尋此筆資料是否存在 /// </summary> /// <param name="id">id值</param> /// <param name="Table_name">table名稱</param> /// <param name="id_name">id名稱</param> /// <returns></returns> public async Task<Boolean> HasExistsWithGuid(string guid, string Table_name, string id_name) { using (IDbConnection conn = GetDbConnection()) { Boolean hasExists = false; conn.Open(); try { var sql = $"SELECT * FROM {Table_name} WHERE {id_name} = @Guid"; var result = await conn.QueryFirstOrDefaultAsync<string>(sql, new { Guid = guid }); if (result != null) { hasExists = true; } } catch (Exception exception) { throw exception; } finally { conn.Close(); } return hasExists; } } /// <summary> /// 根據SQL條件搜尋此筆資料是否存在 /// </summary> /// <param name="sql"></param> /// <returns></returns> public async Task<Boolean> HasExistsWithParam(string sql, object param = null) { using (IDbConnection conn = GetDbConnection()) { Boolean hasExists = false; conn.Open(); try { var result = await conn.QueryFirstOrDefaultAsync<object>(sql, param); if (result != null) { hasExists = true; } } catch (Exception exception) { throw exception; } finally { conn.Close(); } return hasExists; } } /// <summary> /// 直接執行SQL語句 /// </summary> /// <param name="sql"></param> /// <param name="param"></param> /// <returns></returns> public async Task ExecuteSql(string sql, object param = null) { using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { var result = await conn.ExecuteAsync(sql, param); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } #region AddOneReturnId /// <summary> /// 新增table一筆資料 /// </summary> /// <param name="dict">新增資料庫名稱以及值</param> /// <param name="Table_name">資料表名稱</param> /// <returns></returns> public async Task<int> AddOneByCustomTableReturnId(Dictionary<string, object> dict, string Table_name, bool returnId = true) { var id = 0; using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (var trans = conn.BeginTransaction()) { try { List<string> properties = dict.Keys.ToList(); string sql = InsertGenerateString(properties, Table_name); if (returnId) { sql += " SELECT SCOPE_IDENTITY()"; } id = await conn.QueryFirstOrDefaultAsync<int>(sql, dict, trans); //await conn.ExecuteAsync(sql, dict, trans); trans.Commit(); } catch (Exception exception) { trans.Rollback(); throw exception; } finally { conn.Close(); } } } return id; } #endregion AddOneReturnId } }