using Dapper; using Repository.BackendRepository.Interface; using Repository.Helper; using System; using System.Text; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Transactions; using Repository.Models; using System.Data.SqlTypes; using Microsoft.Extensions.Primitives; using System.Web; using Org.BouncyCastle.Utilities.Collections; using System.Reflection; using System.Drawing; using Org.BouncyCastle.Asn1.Mozilla; using System.IO; using System.Diagnostics; using System.Runtime.CompilerServices; using Microsoft.Extensions.Hosting; namespace Repository.BackendRepository.Implement { public class NiagaraDataSynchronizeRepository : BackendRepository, INiagaraDataSynchronizeRepository { private Stopwatch stopwatch = new Stopwatch(); private Stopwatch stopwatchSection = new Stopwatch(); public NiagaraDataSynchronizeRepository(IDatabaseHelper databaseHelper) : base(databaseHelper) { } /// /// 更新import_niagara_tag資料表 /// /// /// /// public async Task InsertNiagaraTagList(List ds, List building, string tag_quantity) { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); StringBuilder sb = new StringBuilder(); try { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); foreach (var b in building) { string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` ( `id` int(11) NOT NULL AUTO_INCREMENT, `db_tags` varchar(50) DEFAULT NULL, `niagara_tags` varchar(50) DEFAULT NULL, `device_area_tag` varchar(50) DEFAULT NULL, `device_building_tag` varchar(50) DEFAULT NULL, `device_system_tag` varchar(50) DEFAULT NULL, `device_name_tag` varchar(50) DEFAULT NULL, `device_floor_tag` varchar(50) DEFAULT NULL, `device_master_tag` varchar(50) DEFAULT NULL, `device_last_name_tag` varchar(50) DEFAULT NULL, `device_serial_tag` varchar(50) DEFAULT NULL, `atDateTime` datetime(1) DEFAULT NULL, `device_full_name` varchar(100) DEFAULT NULL, `is_used` smallint(1) DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } sql = "delete from import_niagara_tag where device_building_tag = '" + b + "' limit 10000"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } } stopwatchSection.Stop(); await KeepTimeLog("Create or delete related building import_niagara_tag", stopwatchSection.ElapsedMilliseconds); //N4資料groupBy後放入import_niagara_tag資料表 var ds2 = ds.GroupBy(x => new { tag_name2 = x.tag_name, displayName2 = x.displayName }).Select(x => new Device_value { tag_name = x.Key.tag_name2, displayName = x.Key.displayName2 }); // StringBuilder sb = new StringBuilder(); bool isDome = false; //是否為巨蛋案 int count = 0; stopwatchSection = new Stopwatch(); stopwatchSection.Start(); foreach (var row in ds2) { if (string.IsNullOrEmpty(row.tag_name)) continue; string[] arrTag = row.tag_name.Split('_'); if (int.Parse(tag_quantity) == 8) { if (arrTag.Length == 8) { sb.Append($@" insert into import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_full_name, atDateTime) values('" + row.tag_name + "', '" + //niagara_tags arrTag[0] + "', '" + //device_area_tag arrTag[1] + "', '" + //device_building_tag arrTag[2] + "', '" + //device_system_tag arrTag[3] + "', '" + //device_name_tag arrTag[4] + "', '" + //device_floor_tag arrTag[5] + "', '" + //device_master_tag arrTag[6] + "', '" + //device_last_name_tag arrTag[7] + "', '" + //device_serial_tag row.displayName + "', " + //device_full_name "now());"); //atDateTime } } else { if (arrTag.Length == 5) { isDome = true; sb.Append($@" insert into import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_model_tag, device_full_name, atDateTime) values('" + row.tag_name + "', '" + //niagara_tags "', '" + //device_area_tag arrTag[0] + "', '" + //device_building_tag arrTag[1] + "', '" + //device_system_tag 巨蛋沒有大類,後面再用關聯的方式補上 arrTag[3] + "', '" + //device_name_tag arrTag[2] + "', '" + //device_floor_tag "', '" + //device_master_tag "', '" + //device_last_name_tag arrTag[4] + "', '" + //device_serial_tag arrTag[3] + "', '" + //device_model_tag row.displayName + "', " + //device_full_name "now());"); //atDateTime //await conn.ExecuteAsync(sb.ToString()); //sb.Clear(); count += 1; if (count >= 100) { count = 0; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } } } stopwatchSection.Stop(); await KeepTimeLog("Insert into import_niagara_tag", stopwatchSection.ElapsedMilliseconds); if (sb.Length > 0) { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); var temp = sb.ToString(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(temp); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("Insert into import_niagara_tag", stopwatchSection.ElapsedMilliseconds); } //巨蛋特殊處理 if (isDome) { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" -- tag 第二碼為小類(除了安全系統之外) update import_niagara_tag set device_name_tag = device_system_tag where (device_system_tag <> 'S' and device_system_tag <> 'CWB' and device_system_tag <> 'B' and (device_system_tag <> 'FM' or device_system_tag <> 'APS' or device_system_tag <> 'VICL')); update import_niagara_tag a join variable b on a.device_name_tag COLLATE utf8mb4_general_ci = b.system_value and b.deleted = 0 and b.system_type = 'device_system_category_layer3' join variable v1 on b.system_parent_id = v1.id set device_system_tag = v1.system_value -- tag 第二碼為小類(除了安全系統之外) where (device_system_tag <> 'S' and device_system_tag <> 'CWB' and device_system_tag <> 'B' and (device_system_tag <> 'FM' or device_system_tag <> 'APS' or device_system_tag <> 'VICL')); -- 安全系統 第二段大類 第四段小類"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("巨蛋特殊處理", stopwatchSection.ElapsedMilliseconds); } stopwatch.Stop(); await KeepTimeLog("InsertNiagaraTagList", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { Console.WriteLine(sb.ToString()); throw exception; } finally { conn.Close(); } } } /// /// 獲取照明開關 是否在 device_node 層 /// /// public async Task getLightSwitchLevel() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); var sql = "select system_value from variable where system_type = 'module_light_switch' "; var module_light_switch = conn.QueryAsync(sql).Result.FirstOrDefault(); conn.Close(); stopwatch.Stop(); await KeepTimeLog("getLightSwitchLevel", stopwatch.ElapsedMilliseconds); return module_light_switch; } } /// /// 更新import_niagara_tag資料表 /// /// /// /// public async Task InsertItemFromNiagara(List ds, List building, bool isFirstAsync) { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { #region 刪除 import_niagara_item資料表中選取的棟別 if (isFirstAsync) { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); foreach (var b in building) { string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` ( `id` int(11) NOT NULL AUTO_INCREMENT, `device_area_tag` varchar(50) DEFAULT NULL, `device_building_tag` varchar(50) DEFAULT NULL, `device_system_tag` varchar(50) DEFAULT NULL, `device_name_tag` varchar(50) DEFAULT NULL, `device_point_name` varchar(50) DEFAULT NULL, `check_status` varchar(50) DEFAULT NULL, `parent_path` varchar(50) DEFAULT NULL, `full_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } sql = "delete from import_niagara_item where device_building_tag = '" + b + "' limit 10000;"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } } stopwatchSection.Stop(); await KeepTimeLog("Create or delete related building import_niagara_tag", stopwatchSection.ElapsedMilliseconds); } #endregion stopwatchSection = new Stopwatch(); stopwatchSection.Start(); ds = ds.GroupBy(x => new { device_area_tag = x.device_area_tag, device_building_tag = x.device_building_tag, device_system_tag = x.device_system_tag, device_name_tag = x.device_name_tag, device_point_name = x.device_point_name, full_name = x.full_name }) .Select(x => new ImpNiaItem { device_area_tag = x.Key.device_area_tag, device_building_tag = x.Key.device_building_tag, device_system_tag = x.Key.device_system_tag, device_name_tag = x.Key.device_name_tag, device_point_name = x.Key.device_point_name, full_name = x.Key.full_name }).ToList(); StringBuilder sb = new StringBuilder(); #region 放入import_niagara_item資料表 foreach (var row in ds) { sb.Append($@" insert import_niagara_item(device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_point_name, parent_path, full_name, is_history) values('" + row.device_area_tag + "', '" + row.device_building_tag + "', '" + row.device_system_tag + "', '" + row.device_name_tag + "', '" + row.device_point_name + "', '" + "" + "', '" + row.full_name + "'," + "0" + ");"); if (sb.Length >= 100) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } var isDome = await GetOneAsync("select system_value from variable where deleted = 0 and system_type = 'project_name';"); if (sb.Length > 0) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("Insert into import_niagara_item", stopwatchSection.ElapsedMilliseconds); if (isDome.Contains("ibms_dome")) { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" update import_niagara_item a join variable b on a.device_name_tag COLLATE utf8mb4_0900_ai_ci = b.system_value COLLATE utf8mb4_0900_ai_ci and b.deleted = 0 and b.system_type = 'device_system_category_layer3' join variable v1 on b.system_parent_id = v1.id set device_system_tag = v1.system_value where (device_system_tag <> 'S' and device_system_tag <> 'CWB' and device_system_tag <> 'B');"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("Insert into import_niagara_item", stopwatchSection.ElapsedMilliseconds); } sb.Clear(); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" update import_niagara_item set full_name = device_point_name where full_name = '' or full_name is null;"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("update device point name where full name is empty or null", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); await RecoverSysTag("import_niagara_item"); stopwatchSection.Stop(); await KeepTimeLog("update import_niagara_item system tag", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"SET SQL_SAFE_UPDATES = 0; update import_niagara_item ini join ( select device_building_tag, device_system_tag, device_name_tag, device_point_name from import_niagara_item_history group by device_building_tag, device_system_tag, device_name_tag, device_point_name ) as inih on ini.device_building_tag = inih.device_building_tag and ini.device_system_tag = inih.device_system_tag and ini.device_name_tag = inih.device_name_tag and ini.device_point_name = inih.device_point_name set ini.is_history = 1"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("update device_item history", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"SET SQL_SAFE_UPDATES = 0; update import_niagara_item ini join ( select distinct device_building_tag, parent_path from import_niagara_item_history ) inih on ini.device_building_tag = inih.device_building_tag set ini.parent_path = inih.parent_path"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("update device_item parent_path", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("InsertItemFromNiagara", stopwatch.ElapsedMilliseconds); //delete the same point in await conn.ExecuteAsync(@"DELETE ini1 FROM import_niagara_item ini1 JOIN ( SELECT DISTINCT ini1.id FROM import_niagara_item ini1 JOIN import_niagara_item ini2 ON ini1.id != ini2.id AND ini1.device_building_tag = ini2.device_building_tag AND ini1.device_system_tag = ini2.device_system_tag AND ini1.device_name_tag = ini2.device_name_tag AND ini1.device_point_name = ini2.device_point_name AND ini1.full_name = ini2.full_name AND ini1.parent_path = ini2.parent_path AND ini1.is_history = ini2.is_history WHERE ini1.id NOT IN ( SELECT MIN(id) FROM import_niagara_item GROUP BY device_building_tag, device_system_tag, device_name_tag, device_point_name, full_name HAVING COUNT(device_point_name) > 1 ) ) AS to_delete ON ini1.id = to_delete.id;"); #endregion } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } /// /// 比對 device /// /// public async Task DeviceComparison(string LightSwitchLevel) { Stopwatch stopwatch = Stopwatch.StartNew(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { // 1. 取得需要新增的 NiagaraTags Stopwatch sw1 = Stopwatch.StartNew(); string sqlGetNiagaraTags = @" SELECT m.* FROM import_niagara_tag m WHERE NOT EXISTS ( SELECT 1 FROM device d WHERE m.niagara_tags = d.device_number );"; List niagaraTagsToAdd = (await conn.QueryAsync(sqlGetNiagaraTags)).ToList(); sw1.Stop(); await KeepTimeLog("filter device item from import_niagara_tag", sw1.ElapsedMilliseconds); // 2. 新增 device 和 device_kind if (niagaraTagsToAdd.Count > 0) { // 2.1. 新增 device Stopwatch sw2 = Stopwatch.StartNew(); List sqlInsertDeviceList = new List(); foreach (var data in niagaraTagsToAdd) { if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G") { // 燈具新增 device_node continue; } string sqlInsertDevice = @" INSERT INTO device (device_guid, deleted, status, priority, is_link, device_area_tag, device_building_tag, device_system_tag, device_name_tag, full_name, device_floor_tag, device_master, device_last_name, device_serial_tag, device_model_tag, device_number, device_system_category_layer3, visible, created_at, updated_at) select uuid(), 0, 1, 0, 1, @device_area_tag, @device_building_tag, @device_system_tag, @device_name_tag, @full_name, @device_floor_tag, @device_master_tag, @device_last_name_tag, @device_serial_tag, @device_model_tag, @niagara_tags, @device_system_tag, 1, now(), now() WHERE NOT EXISTS (SELECT 1 FROM device WHERE device_number = @niagara_tags); "; sqlInsertDeviceList.Add(sqlInsertDevice); // 先暫存SQL語法,等等一次執行 } // 2.1.1 分批執行新增 device int batchSize = 100; for (int i = 0; i < sqlInsertDeviceList.Count; i += batchSize) { //建立參數 var batch = niagaraTagsToAdd.Skip(i).Take(batchSize).ToList(); //建立參數化查詢要用的物件 List parameters = new List(); foreach (var data in batch) { parameters.Add(new { device_area_tag = data.device_area_tag, device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag, full_name = data.device_full_name, device_floor_tag = data.device_floor_tag, device_master_tag = data.device_master_tag, device_last_name_tag = data.device_last_name_tag, device_serial_tag = data.device_serial_tag, device_model_tag = data.device_model_tag, niagara_tags = data.niagara_tags }); } //建立多條Insert語法,可以搭配Dapper的參數化查詢 string insertSql = string.Join(" ", sqlInsertDeviceList.Take(batchSize)); using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢 scope.Complete(); } } sw2.Stop(); await KeepTimeLog("insert into device", sw2.ElapsedMilliseconds); // 2.2. 新增 device_kind Stopwatch sw3 = Stopwatch.StartNew(); // 建立 device_kind 時需要用到的資料結構 var deviceKindData = niagaraTagsToAdd.GroupBy(x => new { x.device_building_tag, x.device_system_tag, x.device_name_tag }).Select(g => new { g.Key.device_building_tag, g.Key.device_system_tag, g.Key.device_name_tag }).ToList(); foreach (var data in deviceKindData) { // 檢查 device_kind 是否已存在 (改成使用 EXISTS 子查詢) string sqlCheckDeviceKind = @" SELECT EXISTS ( SELECT 1 FROM device_kind WHERE device_building_tag = @device_building_tag AND device_system_tag = @device_system_tag AND device_name_tag = @device_name_tag );"; var parameters = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag }; bool deviceKindExists = await conn.ExecuteScalarAsync(sqlCheckDeviceKind, parameters); // 使用參數化查詢 if (!deviceKindExists) { // 新增 device_kind string sqlInsertDeviceKind = @" INSERT INTO device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag, device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent, created_by, created_at, is_link) VALUES (uuid(), @device_building_tag, @device_system_tag, @device_name_tag, 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 1);"; var parameters2 = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag }; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlInsertDeviceKind, parameters2); // 使用參數化查詢 scope.Complete(); } } } sw3.Stop(); await KeepTimeLog("insert into device_kind", sw3.ElapsedMilliseconds); } // 3. device_kind process for cctv Stopwatch sw4 = Stopwatch.StartNew(); // 3.1 更新 device 的 model tag string sqlUpdateCCTVModel = @" UPDATE device d JOIN import_niagara_tag n ON d.device_number = n.niagara_tags SET d.device_model_tag = n.device_model_tag WHERE d.device_system_tag = 'S' AND d.device_name_tag = 'C' AND (d.device_model_tag IS NULL OR d.device_model_tag = '');"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateCCTVModel); // 使用參數化查詢 scope.Complete(); } sw4.Stop(); await KeepTimeLog("update cctv model is null or empty", sw4.ElapsedMilliseconds); // 3.2 取得 CCTV 相關資料,並新增 device_kind (邏輯同 2.2,但需要額外考量 device_model_tag) Stopwatch sw5 = Stopwatch.StartNew(); string sqlGetCCTVData = @"SELECT * FROM import_niagara_tag WHERE device_system_tag = 'S' AND device_name_tag = 'C';"; var cctvData = await conn.QueryAsync(sqlGetCCTVData); // 建立 device_kind 時需要用到的資料結構 var cctvKindData = cctvData.GroupBy(x => new { x.device_building_tag, x.device_system_tag, x.device_name_tag, x.device_model_tag }).Select(g => new { g.Key.device_building_tag, g.Key.device_system_tag, g.Key.device_name_tag, g.Key.device_model_tag }).ToList(); foreach (var data in cctvKindData) { // 檢查 device_kind 是否已存在 (改成使用 EXISTS 子查詢) string sqlCheckDeviceKind = @" SELECT EXISTS ( SELECT 1 FROM device_kind WHERE device_building_tag = @device_building_tag AND device_system_tag = @device_system_tag AND device_name_tag = @device_name_tag AND device_model_tag = @device_model_tag );"; var parameters = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag, device_model_tag = data.device_model_tag }; bool deviceKindExists = await conn.ExecuteScalarAsync(sqlCheckDeviceKind, parameters); if (!deviceKindExists) { // 新增 device_kind string sqlInsertDeviceKind = @" INSERT INTO device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag, device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent, created_by, created_at, device_model_tag, is_link) VALUES (uuid(), @device_building_tag, @device_system_tag, @device_name_tag, 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), @device_model_tag, 1);"; var parameters2 = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag, device_model_tag = data.device_model_tag }; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlInsertDeviceKind, parameters2); // 使用參數化查詢 scope.Complete(); } } } sw5.Stop(); await KeepTimeLog("insert cctv device_kind", sw5.ElapsedMilliseconds); // 3.3 更新 device_kind 的 is_link (邏輯複雜,需要仔細確認SQL語法) Stopwatch sw6 = Stopwatch.StartNew(); // 先更新 device_kind 的 is_link 為 0 string sqlUpdateDeviceKindIsLinkToZero = @" UPDATE device_kind SET is_link = 0 WHERE device_system_tag = 'S' AND device_name_tag = 'C' AND NOT EXISTS ( SELECT 1 FROM import_niagara_tag WHERE device_system_tag = device_kind.device_system_tag AND device_name_tag = device_kind.device_name_tag AND device_model_tag = device_kind.device_model_tag );"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateDeviceKindIsLinkToZero); // 使用參數化查詢 scope.Complete(); } // 再更新 device_kind 的 is_link 為 1 string sqlUpdateDeviceKindIsLinkToOne = @" UPDATE device_kind SET is_link = 1 WHERE device_system_tag = 'S' AND device_name_tag = 'C' AND EXISTS ( SELECT 1 FROM import_niagara_tag WHERE device_system_tag = device_kind.device_system_tag AND device_name_tag = device_kind.device_name_tag AND device_model_tag = device_kind.device_model_tag );"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateDeviceKindIsLinkToOne); // 使用參數化查詢 scope.Complete(); } sw6.Stop(); await KeepTimeLog("insert/update cctv model is_link", sw6.ElapsedMilliseconds); // 4. device_node 新增 (邏輯同 2.1,需要調整 SQL 語法和參數) Stopwatch sw7 = Stopwatch.StartNew(); string sqlGetNiagaraTagsForNode = @" SELECT m.* FROM import_niagara_tag m WHERE NOT EXISTS ( SELECT 1 FROM device_node d WHERE m.niagara_tags = d.device_number );"; List niagaraTagsToAddForNode = (await conn.QueryAsync(sqlGetNiagaraTagsForNode)).ToList(); if (niagaraTagsToAddForNode.Count > 0) { // 4.1. 新增 device_node List sqlInsertDeviceNodeList = new List(); foreach (var data in niagaraTagsToAddForNode) { if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G") { // 燈具新增 device_node string sqlInsertDeviceNode = @" INSERT INTO device_node (device_node_guid, deleted, device_guid, device_number, full_name, created_by, created_at, updated_at) VALUES (uuid(), 0, '', @device_number, @full_name, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), now());"; sqlInsertDeviceNodeList.Add(sqlInsertDeviceNode); } } //4.1.1 分批執行新增device node int batchSizeNode = 100; for (int i = 0; i < sqlInsertDeviceNodeList.Count; i += batchSizeNode) { //建立參數 var batch = niagaraTagsToAddForNode.Skip(i).Take(batchSizeNode).ToList(); //建立參數化查詢要用的物件 List parameters = new List(); foreach (var data in batch) { parameters.Add(new { device_number = data.niagara_tags, full_name = data.device_full_name, }); } //建立多條Insert語法,可以搭配Dapper的參數化查詢 string insertSql = string.Join(" ", sqlInsertDeviceNodeList.Take(batchSizeNode)); using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢 scope.Complete(); } } } sw7.Stop(); await KeepTimeLog("insert into device_node", sw7.ElapsedMilliseconds); // 5. 更新 device 的 is_link Stopwatch sw8 = Stopwatch.StartNew(); // 先更新 device 的 is_link 為 1 (邏輯簡單,直接使用 UPDATE JOIN) string sqlUpdateDeviceIsLinkToOne = @" UPDATE device d JOIN import_niagara_tag i ON d.device_number = i.niagara_tags SET d.is_link = 1, d.deleted = 0;"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateDeviceIsLinkToOne); // 使用參數化查詢 scope.Complete(); } sw8.Stop(); await KeepTimeLog("update device is_link = 1, deleted = 0", sw8.ElapsedMilliseconds); // 再更新 device 的 is_link 為 0 (邏輯需要調整,使用 NOT EXISTS 子查詢) Stopwatch sw9 = Stopwatch.StartNew(); string sqlUpdateDeviceIsLinkToZero = @" UPDATE device SET is_link = 0 WHERE is_link = 1 AND NOT EXISTS ( SELECT 1 FROM import_niagara_tag WHERE device.device_number = import_niagara_tag.niagara_tags );"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateDeviceIsLinkToZero); // 使用參數化查詢 scope.Complete(); } sw9.Stop(); await KeepTimeLog("update device is_link = 0", sw9.ElapsedMilliseconds); // 6. 更新 device_node 的 is_link (邏輯同 5,需要調整 SQL 語法和參數) Stopwatch sw10 = Stopwatch.StartNew(); string sqlUpdateDeviceNodeIsLinkToZero = @" UPDATE device_node SET is_link = 0 WHERE is_link = 1 AND NOT EXISTS ( SELECT 1 FROM import_niagara_tag WHERE device_node.device_number = import_niagara_tag.niagara_tags );"; using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sqlUpdateDeviceNodeIsLinkToZero); // 使用參數化查詢 scope.Complete(); } sw10.Stop(); await KeepTimeLog("update device_node is_link = 0", sw10.ElapsedMilliseconds); //Main總時間 stopwatch.Stop(); await KeepTimeLog("DeviceComparison", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { throw; // 保留原始堆疊追蹤 } finally { if (conn.State == ConnectionState.Open) { conn.Close(); } } } } /// /// 比對 device_item /// /// public async Task DeviceItemComparison() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); List result; StringBuilder sb = new StringBuilder(); sb.Append($@" SELECT m.device_point_name, m.is_history, m.device_building_tag, m.device_system_tag, m.device_name_tag, m.parent_path, m.full_name FROM import_niagara_item m left JOIN ( select device_building_tag, device_system_tag, device_name_tag, points from device_item where deleted = 0 ) d ON m.device_system_tag = d.device_system_tag and m.device_name_tag = d.device_name_tag and m.device_point_name = d.points and m.device_building_tag = d.device_building_tag where d.points is null;"); result = (await conn.QueryAsync(sb.ToString())).ToList(); sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("filter device_item from import_niagara_item", stopwatchSection.ElapsedMilliseconds); #region 新增至device, is_link = 1 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); if (result.Count > 0) { foreach (var data in result) { var isControll = 0; var isBool = 0; if (data.device_point_name == "ER" || data.device_point_name == "AL" || data.device_point_name == "ST") { isControll = 1; } if (data.device_point_name == "ER" || data.device_point_name == "ST") { isBool = 1; } sb.Append($@"insert device_item(deleted, points, is_show, is_show_riserDiagram, is_controll, is_bool, is_show_history, is_link, device_system_tag, device_name_tag, device_building_tag, full_name, parent_path, created_at, updated_at) VALUES (0, '" + data.device_point_name + "', 1, 0, " + isControll + "," + isBool + "," + data.is_history + ", 1, '" + data.device_system_tag + "', '" + data.device_name_tag + "', '" + data.device_building_tag + "', '" + data.full_name + "', '" + data.parent_path + "', " + "now(), now());"); } if (sb.Length > 0) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } stopwatchSection.Stop(); await KeepTimeLog("insert into device_item", stopwatchSection.ElapsedMilliseconds); #endregion //device有,niagara沒有,is_link 更新成 0 //sb.Append($@" SET SQL_SAFE_UPDATES = 0; // UPDATE device_item d LEFT JOIN import_niagara_item m // ON d.device_system_tag = m.device_system_tag and d.device_name_tag = m.device_name_tag and d.points = m.device_point_name // SET d.is_link = 0, d.is_show_history = 0 // WHERE m.device_point_name IS NULL"); //本次有匯入的 isLink 改為 1, 沒有的 isLink = 0 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" SET SQL_SAFE_UPDATES = 0; UPDATE device_item d LEFT JOIN ( SELECT device_system_tag, device_name_tag, device_point_name, full_name, device_building_tag FROM import_niagara_item LIMIT 100000 -- Specify your desired limit here ) m ON d.device_system_tag = m.device_system_tag AND d.device_name_tag = m.device_name_tag AND d.points = m.device_point_name AND d.device_building_tag = m.device_building_tag SET d.is_link = CASE WHEN m.device_point_name IS NULL THEN 0 ELSE 1 END;"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("update device_item is_link", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" SET SQL_SAFE_UPDATES = 0; UPDATE device_item d LEFT JOIN ( SELECT m.device_system_tag, m.device_name_tag, m.device_point_name, m.full_name, device_building_tag, date(created_at) as created_at FROM import_niagara_item m WHERE m.is_history = 1 LIMIT 100000 -- Specify your desired limit here ) AS subquery ON d.device_system_tag = subquery.device_system_tag AND d.device_name_tag = subquery.device_name_tag AND d.points = subquery.device_point_name AND d.device_building_tag = subquery.device_building_tag SET d.is_show_history = CASE WHEN subquery.device_point_name IS NULL THEN 0 ELSE 1 END"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("update device_item is_show_history", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("DeviceItemComparison", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } /// /// 新增資料至 buildingMenu /// /// public async Task InsertBuildingMenu() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { List result; StringBuilder sb = new StringBuilder(); #region comparison building_menu and import_niagara_tag stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" select a.* from ( select device_building_tag, device_system_tag, device_name_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag ) AS a LEFT JOIN building_menu b ON a.device_building_tag COLLATE utf8mb4_0900_ai_ci = b.device_building_tag COLLATE utf8mb4_0900_ai_ci and a.device_system_tag COLLATE utf8mb4_0900_ai_ci = b.device_system_tag COLLATE utf8mb4_0900_ai_ci and a.device_name_tag COLLATE utf8mb4_0900_ai_ci = b.sub_system_tag COLLATE utf8mb4_0900_ai_ci WHERE b.device_building_tag IS NULL"); result = (await conn.QueryAsync(sb.ToString())).ToList(); #endregion sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("filter building_menu from import_niagara_tag", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); if (result.Count > 0) { foreach (var data in result) { StringBuilder sqlString = new StringBuilder(); sqlString.Append(@"select * from building_menu where building_tag = '" + data.device_building_tag + "' and main_system_tag = '" + data.device_system_tag + "' and sub_system_tag = '" + data.device_name_tag + "'"); var bm = (await conn.QueryAsync(sqlString.ToString())).ToList(); #region insert building_menu if (bm.Count == 0) { sb.Append(@$"insert building_menu(building_tag, main_system_tag, sub_system_tag, device_building_tag, device_system_tag, left_drawing, left_icon_click, left_icon_click_url_width, left_icon_click_url_height, left_planimetric_click, is_link, created_by, created_at, updated_by, updated_at) values('{data.device_building_tag}', '{data.device_system_tag}', '{data.device_name_tag}', '{data.device_building_tag}', '{data.device_system_tag}', 4, 1, 0, 0, 1, 1, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now());"); } #endregion } if (sb.Length > 0) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } stopwatchSection.Stop(); await KeepTimeLog("insert into building_menu", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); //building_menu有,import_niagara_tag沒有,is_link 更新成 0 sb.Append($@" SET SQL_SAFE_UPDATES = 0; UPDATE building_menu b LEFT JOIN ( select device_building_tag, device_system_tag, device_name_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag ) AS a ON b.building_tag COLLATE utf8mb4_0900_ai_ci = a.device_building_tag COLLATE utf8mb4_0900_ai_ci and a.device_system_tag COLLATE utf8mb4_0900_ai_ci = b.main_system_tag COLLATE utf8mb4_0900_ai_ci and a.device_name_tag COLLATE utf8mb4_0900_ai_ci = b.sub_system_tag COLLATE utf8mb4_0900_ai_ci SET b.is_link = 0 WHERE a.device_building_tag IS NULL and b.is_link < 2"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("update building_menu is_link = 0", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"SET SQL_SAFE_UPDATES = 0; UPDATE building_menu b LEFT JOIN ( select device_building_tag, device_system_tag, device_name_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag ) AS a ON b.building_tag COLLATE utf8mb4_0900_ai_ci = a.device_building_tag COLLATE utf8mb4_0900_ai_ci and a.device_system_tag COLLATE utf8mb4_0900_ai_ci = b.main_system_tag COLLATE utf8mb4_0900_ai_ci and a.device_name_tag COLLATE utf8mb4_0900_ai_ci = b.sub_system_tag COLLATE utf8mb4_0900_ai_ci SET b.is_link = 1 WHERE a.device_building_tag IS NOT NULL and b.is_link < 2"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("update building_menu is_link = 1", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("InsertBuildingMenu", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } /// /// 根據Building_menu 更新 AuthPage /// /// public async Task UpdateAuthPageByBuildingMenu() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { List result; StringBuilder sb = new StringBuilder(); //building_menu有,auth_page沒有,且variable有對應的大小類,新增這些權限 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"SELECT vm.system_key MainName,vs.system_key SubName,bm.building_tag,vs.id ShowView from building_menu bm left join(SELECT vm.system_value main_system_tag,vs.system_value sub_system_tag,a.building_tag FROM `auth_page` a join variable vs on a.ShowView = vs.id and vs.deleted = 0 join variable vm on vs.system_parent_id = vm.id and vm.deleted = 0 GROUP BY main_system_tag, sub_system_tag, building_tag) a on a.main_system_tag = bm.main_system_tag and a.sub_system_tag = bm.sub_system_tag and a.building_tag = bm.building_tag join variable vs on bm.sub_system_tag = vs.system_value and vs.system_type = 'device_system_category_layer3' and vs.deleted = 0 join variable vm on bm.main_system_tag = vm.system_value and vm.system_type = 'device_system_category_layer2'and vm.deleted = 0 WHERE bm.is_link = 1 and a.building_tag is null ORDER BY vs.id"); result = (await conn.QueryAsync(sb.ToString())).ToList(); sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("filter auth_page from building_menu", stopwatchSection.ElapsedMilliseconds); var max = (await conn.QueryAsync("select ifnull((select Max(CONVERT(SUBSTRING(AuthCode,2,5), SIGNED)) AuthCode from auth_page ap where ap.AuthCode like 'F%'),'0') AuthCode")).First(); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); if (result.Count > 0) { foreach (var data in result) { StringBuilder sqlString = new StringBuilder(); sb.Append(@$"insert into auth_page(AuthCode, AuthType, MainName, SubName, building_tag, ShowView, created_at) values ('F{++max}', '1', '{data.MainName}', '{data.SubName}', '{data.building_tag}', '{data.ShowView}', Now());"); } if (sb.Length > 0) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } stopwatchSection.Stop(); await KeepTimeLog("insert into auth_page", stopwatchSection.ElapsedMilliseconds); //auth_page有,building_menu沒有,把auth_code對應的role_auth也一併刪除 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"DELETE FROM role_auth WHERE AuthCode in (SELECT ap.AuthCode FROM (SELECT vm.system_value main_system_tag,vs.system_value sub_system_tag,a.* FROM `auth_page` a join variable vs on a.ShowView = vs.id and vs.deleted = 0 join variable vm on vs.system_parent_id = vm.id and vm.deleted = 0 GROUP BY main_system_tag, sub_system_tag, building_tag) ap LEFT JOIN ( SELECT bm.main_system_tag, bm.sub_system_tag, bm.building_tag FROM building_menu bm WHERE bm.is_link = 1 ) bm ON ap.building_tag = bm.building_tag AND bm.main_system_tag = ap.main_system_tag AND bm.sub_system_tag = ap.sub_system_tag WHERE bm.building_tag IS NULL);"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("auth_page有,building_menu沒有,把auth_code對應的role_auth也一併刪除", stopwatchSection.ElapsedMilliseconds); //auth_page有,building_menu沒有,刪除這些權限 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@"DELETE FROM auth_page WHERE AuthCode in (SELECT ap.AuthCode FROM (SELECT vm.system_value main_system_tag,vs.system_value sub_system_tag,a.* FROM `auth_page` a join variable vs on a.ShowView = vs.id and vs.deleted = 0 join variable vm on vs.system_parent_id = vm.id and vm.deleted = 0 GROUP BY main_system_tag, sub_system_tag, building_tag) ap LEFT JOIN ( SELECT bm.main_system_tag, bm.sub_system_tag, bm.building_tag FROM building_menu bm WHERE bm.is_link = 1 ) bm ON ap.building_tag = bm.building_tag AND bm.main_system_tag = ap.main_system_tag AND bm.sub_system_tag = ap.sub_system_tag WHERE bm.building_tag IS NULL);"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("auth_page有,building_menu沒有,刪除這些權限", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("UpdateAuthPageByBuildingMenu", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } /// /// 新增資料至 subSystemFloor /// /// public async Task InsertSubSystemFloor() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { List result; StringBuilder sb = new StringBuilder(); #region comparison sub_system_floor and import_niagara_tag stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" select a.* from ( select device_building_tag, device_system_tag, device_name_tag, device_floor_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag, device_floor_tag ) AS a LEFT JOIN sub_system_floor b ON a.device_building_tag COLLATE utf8mb4_0900_ai_ci = b.building_tag COLLATE utf8mb4_0900_ai_ci and a.device_system_tag COLLATE utf8mb4_0900_ai_ci = b.main_system_tag COLLATE utf8mb4_0900_ai_ci and a.device_name_tag COLLATE utf8mb4_0900_ai_ci = b.sub_system_tag COLLATE utf8mb4_0900_ai_ci and a.device_floor_tag COLLATE utf8mb4_0900_ai_ci = b.floor_tag COLLATE utf8mb4_0900_ai_ci WHERE b.building_tag IS NULL"); result = (await conn.QueryAsync(sb.ToString())).ToList(); sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("filter subsystem floor from import_niagara_tag", stopwatchSection.ElapsedMilliseconds); #endregion stopwatchSection = new Stopwatch(); stopwatchSection.Start(); if (result.Count > 0) { foreach (var data in result) { #region insert building_menu sb.Append(@"insert sub_system_floor(building_tag, main_system_tag, sub_system_tag, floor_tag, is_link, created_by, created_at, updated_by, updated_at) VALUES ('" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag + "', '" + data.device_floor_tag + "', " + "1, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now());"); #endregion } if (sb.Length > 0) { using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } } stopwatchSection.Stop(); await KeepTimeLog("insert into subsystem floor", stopwatchSection.ElapsedMilliseconds); //building_menu有,import_niagara_tag沒有,is_link 更新成 0 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" SET SQL_SAFE_UPDATES = 0; UPDATE sub_system_floor b LEFT JOIN ( select device_building_tag, device_system_tag, device_name_tag, device_floor_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag, device_floor_tag ) AS a ON b.building_tag COLLATE utf8mb4_0900_ai_ci = a.device_building_tag COLLATE utf8mb4_0900_ai_ci and b.main_system_tag COLLATE utf8mb4_0900_ai_ci = a.device_system_tag COLLATE utf8mb4_0900_ai_ci and b.sub_system_tag COLLATE utf8mb4_0900_ai_ci = a.device_name_tag COLLATE utf8mb4_0900_ai_ci and b.floor_tag COLLATE utf8mb4_0900_ai_ci = a.device_floor_tag COLLATE utf8mb4_0900_ai_ci SET b.is_link = 0 WHERE a.device_building_tag IS NULL"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("update subsystem floor is_link = 0", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" SET SQL_SAFE_UPDATES = 0; UPDATE sub_system_floor b LEFT JOIN ( select device_building_tag, device_system_tag, device_name_tag, device_floor_tag from import_niagara_tag group by device_building_tag, device_system_tag, device_name_tag, device_floor_tag ) AS a ON b.building_tag COLLATE utf8mb4_0900_ai_ci = a.device_building_tag COLLATE utf8mb4_0900_ai_ci and b.main_system_tag COLLATE utf8mb4_0900_ai_ci = a.device_system_tag COLLATE utf8mb4_0900_ai_ci and b.sub_system_tag COLLATE utf8mb4_0900_ai_ci = a.device_name_tag COLLATE utf8mb4_0900_ai_ci and b.floor_tag COLLATE utf8mb4_0900_ai_ci = a.device_floor_tag COLLATE utf8mb4_0900_ai_ci SET b.is_link = 1 WHERE a.device_building_tag IS NOT NULL"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("update subsystem floor is_link = 1", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("InsertSubSystemFloor", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } /// /// 檢查device內FullName為空的值,以device_Name取代 /// /// public async Task CheckFullNameEmptyReplaceByDeviceName() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { StringBuilder sb = new StringBuilder(); sb.Append(@"SET SQL_SAFE_UPDATES = 0; update device set full_name=device_number where full_Name='';"); await conn.ExecuteAsync(sb.ToString()); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } stopwatch.Stop(); await KeepTimeLog("CheckFullNameEmptyReplaceByDeviceName", stopwatch.ElapsedMilliseconds); } /// /// 檢查device_item內FullName為空的值,以points取代 /// /// public async Task ItemCheckFullNameEmptyReplaceByDeviceName() { stopwatch = new Stopwatch(); stopwatch.Start(); //檢查是否有空值 using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { StringBuilder sb = new StringBuilder(); sb.Append("update device_item set full_name = points where full_Name = '''''';"); await conn.ExecuteAsync(sb.ToString()); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } stopwatch.Stop(); await KeepTimeLog("ItemCheckFullNameEmptyReplaceByDeviceName", stopwatch.ElapsedMilliseconds); } /// /// 檢查device的full_name與niagara device_full_name不同者 覆蓋 /// /// public async Task CheckDiffFullNameAndCover() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled, new TimeSpan (0, 0, 200))) { try { StringBuilder sb = new StringBuilder(); sb.Append(@"SET SQL_SAFE_UPDATES = 0; UPDATE device AS d JOIN import_niagara_tag AS i ON d.device_number = i.niagara_tags SET d.full_name = i.device_full_name WHERE d.full_name <> i.device_full_name; SET SQL_SAFE_UPDATES = 1;"); await conn.ExecuteAsync(sb.ToString()); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } stopwatch.Stop(); await KeepTimeLog("CheckDiffFullNameAndCover", stopwatch.ElapsedMilliseconds); } /// /// 比對 device_item full_name 與 import_niagara_item full_name是否相同 /// 不同則覆蓋 /// /// public async Task CheckItemDiffFullNameAndCover() { stopwatch = new Stopwatch(); stopwatch.Start(); //檢查 using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { StringBuilder sb = new StringBuilder(); sb.Append($@"UPDATE device_item d INNER JOIN ( SELECT m.device_system_tag, m.device_name_tag, m.device_point_name, m.full_name FROM import_niagara_item m join device_item d LIMIT 100000 -- Specify your desired limit here ) AS subquery ON d.device_system_tag = subquery.device_system_tag AND d.device_name_tag = subquery.device_name_tag AND d.points = subquery.device_point_name SET d.full_name = subquery.full_name WHERE d.full_name <> subquery.full_name"); await conn.ExecuteAsync(sb.ToString()); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } stopwatch.Stop(); await KeepTimeLog("CheckItemDiffFullNameAndCover", stopwatch.ElapsedMilliseconds); } /// /// 先將device_item 的is_show_history全部關掉 /// 根據niagara輸入資料來決定要開哪些點 /// /// public async Task CheckItemIsShowHistory() { stopwatch = new Stopwatch(); stopwatch.Start(); //先將所有is_show_history關閉,niagara有的才開啟 using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { StringBuilder sb = new StringBuilder(); //先全部關閉 sb.Append("update device_item set is_show_history=0;"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); sb.Append($@"SET SQL_SAFE_UPDATES = 0; update device_item di JOIN ( select distinct device_system_tag, device_name_tag, device_point_name, full_name, device_building_tag from import_niagara_item where is_history = 1 limit 100000 ) niagara ON di.device_system_tag = niagara.device_system_tag AND di.device_name_tag = niagara.device_name_tag AND di.points = niagara.device_point_name AND di.full_name = niagara.full_name AND di.device_building_tag = niagara.device_building_tag set di.is_show_history = 1"); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } } catch (Exception exception) { throw exception; } finally { conn.Close(); } } stopwatch.Stop(); await KeepTimeLog("getLightSwitchLevel", stopwatch.ElapsedMilliseconds); } public async Task DeviceDisasterAysnc(List dv) { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); StringBuilder sb = new StringBuilder(); List deviceDisaster = new List(); List device = new List(); using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled)) { try { await conn.ExecuteAsync("TRUNCATE TABLE device_disaster"); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append("select * from device_disaster;"); deviceDisaster = (await conn.QueryAsync(sb.ToString())).ToList(); sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("select all device_disaster", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append("select * from device where deleted = 0;"); device = (await conn.QueryAsync(sb.ToString())).ToList(); stopwatchSection.Stop(); await KeepTimeLog("select all device", stopwatchSection.ElapsedMilliseconds); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } stopwatchSection = new Stopwatch(); stopwatchSection.Start(); // 過濾 dv 集合,只保留設備編號有效的項目 dv = dv.Where(x => { string[] parts = x.value.Split('/'); // 確認陣列長度是否足夠長,並且設備編號(索引為6)存在於 device 集合中 if (parts.Length > 6) { string deviceNumber = parts[6]; return device.Any(d => d.device_number == deviceNumber); } else { // 如果陣列長度不足,或者設備編號無效,則返回 false,表示不保留此項目 return false; } }).ToList(); //dv = dv.Where(x => device.Any(d => d.device_number == x.value.Split('/')[6])).ToList(); sb.Clear(); var updateList = dv.Where(x => deviceDisaster.Any(dd => dd.device_number == x.value.Split('/')[6] && dd.device_system_value != x.disasterValue)).ToList(); foreach (var d in updateList) { string device_number = d.value.Split('/')[6]; sb.Append($"update device_disaster set device_system_value = '{d.disasterValue}' where device_number = '{device_number}'; "); } var insertList = dv.Where(x => !deviceDisaster.Any(dd => dd.device_number == x.value.Split('/')[6])).ToList(); foreach (var d in insertList) { string device_number = d.value.Split('/')[6]; string device_guid = device.Where(x => x.device_number == device_number).Select(x => x.device_guid).FirstOrDefault(); string device_system_tag = device.Where(x => x.device_number == device_number).Select(x => x.device_system_tag).FirstOrDefault(); string device_name_tag = device.Where(x => x.device_number == device_number).Select(x => x.device_name_tag).FirstOrDefault(); var check = (await conn.QueryAsync($"select device_guid from device_disaster where device_guid = '{device_guid}' and device_system_value = '{d.disasterValue}'")).FirstOrDefault(); if (string.IsNullOrEmpty(check)) { sb.Append($@"insert into device_disaster (device_guid, device_system_value, device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_serial_tag, device_number) values ('{device_guid}', '{d.disasterValue}', '{device_number.Split('_')[0]}', '{device_system_tag}', '{device_name_tag}', '{device_number.Split('_')[2]}', '{device_number.Split('_')[4]}', '{device_number}'); "); await conn.ExecuteAsync(sb.ToString()); sb.Clear(); } } using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { if (!string.IsNullOrEmpty(sb.ToString())) await conn.ExecuteAsync(sb.ToString()); } catch (Exception ex) { throw ex; } finally { conn.Close(); } } stopwatchSection.Stop(); await KeepTimeLog("update or insert into device_disaster", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("DeviceDisasterAysnc", stopwatch.ElapsedMilliseconds); } } /// /// InsertFloor /// /// public async Task InsertFloor() { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { List result; StringBuilder sb = new StringBuilder(); #region comparison floor and sub_system_floor stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Append($@" select tag.* from ( select device_building_tag, device_floor_tag from import_niagara_tag group by device_building_tag, device_floor_tag ) AS tag LEFT JOIN floor f ON tag.device_building_tag COLLATE utf8mb4_0900_ai_ci = f.building_tag COLLATE utf8mb4_0900_ai_ci and tag.device_floor_tag COLLATE utf8mb4_0900_ai_ci = f.full_name COLLATE utf8mb4_0900_ai_ci and f.deleted = 0 WHERE f.building_tag IS NULL;"); result = (await conn.QueryAsync(sb.ToString())).ToList(); sb.Clear(); stopwatchSection.Stop(); await KeepTimeLog("filter floor from import_niagara_tag", stopwatchSection.ElapsedMilliseconds); #endregion #region insert floor stopwatchSection = new Stopwatch(); stopwatchSection.Start(); if (result.Count > 0) { Dictionary floorPriority = new Dictionary(); foreach (var data in result) { FloorPriority fp = (await conn.QueryAsync($@"select building_tag, max(priority) as priority from floor where building_tag = '{data.device_building_tag}' and deleted = 0 group by building_tag;")).FirstOrDefault(); int priority = 0; if (fp == null && floorPriority.GetValueOrDefault(data.device_building_tag) == 0) floorPriority.Add(data.device_building_tag, 0); else if (fp != null && floorPriority.GetValueOrDefault(fp.building_tag) == 0) floorPriority.Add(fp.building_tag, fp.Priority); priority = ++floorPriority[data.device_building_tag]; sb.Append($@"insert into floor(floor_guid, building_tag, deleted, status, full_name, priority, created_by, created_at) VALUES (uuid(), '{data.device_building_tag}', 0, 1, '{data.device_floor_tag}', {priority}, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now());"); } if (sb.Length > 0) { await conn.ExecuteAsync(sb.ToString()); sb.Clear(); } } stopwatchSection.Stop(); await KeepTimeLog("insert into floor", stopwatchSection.ElapsedMilliseconds); #endregion #region update unuse floor with niagara data stopwatchSection = new Stopwatch(); stopwatchSection.Start(); var floor = (await conn.QueryAsync($@"select f1.* from floor as f1 left join ( select f.floor_guid from ( select device_building_tag, device_floor_tag from import_niagara_tag group by device_building_tag, device_floor_tag ) AS tag LEFT JOIN floor f ON tag.device_building_tag COLLATE utf8mb4_0900_ai_ci = f.building_tag COLLATE utf8mb4_0900_ai_ci and tag.device_floor_tag COLLATE utf8mb4_0900_ai_ci = f.full_name COLLATE utf8mb4_0900_ai_ci and f.deleted = 0 ) as f2 on f1.floor_guid = f2.floor_guid where f2.floor_guid is null and f1.deleted = 0;")).ToList(); if (floor.Count > 0) { sb.Clear(); foreach (var f in floor) { sb.Append($"update floor set deleted = 1 where floor_guid = '{f.Floor_guid}';"); } await conn.ExecuteAsync(sb.ToString()); } stopwatchSection.Stop(); await KeepTimeLog("update floor deleted = 1", stopwatchSection.ElapsedMilliseconds); stopwatch.Stop(); await KeepTimeLog("InsertFloor", stopwatch.ElapsedMilliseconds); #endregion } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } } public async Task InsertItemFromNiagara_History(List ds, List building) { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { conn.Open(); try { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); //改成每次都新增 string sql = @"SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for import_niagara_item_history -- ---------------------------- DROP TABLE IF EXISTS `import_niagara_item_history`; CREATE TABLE `import_niagara_item_history` ( `id` int(11) NOT NULL AUTO_INCREMENT, `device_number` varchar(50) NULL DEFAULT NULL COMMENT '完整 TagName 設備編號', `device_area_tag` varchar(50) NULL DEFAULT NULL, `device_building_tag` varchar(50) NULL DEFAULT NULL, `device_system_tag` varchar(50) NULL DEFAULT NULL, `device_name_tag` varchar(50) NULL DEFAULT NULL, `device_floor_tag` varchar(50) NULL DEFAULT NULL, `device_master_tag` varchar(50) NULL DEFAULT NULL, `device_last_name_tag` varchar(50) NULL DEFAULT NULL, `device_serial_tag` varchar(50) NULL DEFAULT NULL, `device_point_name` varchar(50) NULL DEFAULT NULL, `parent_path` varchar(50) NULL DEFAULT NULL, `is_history` bit(1) NULL DEFAULT b'0', `full_name` varchar(50) NULL DEFAULT NULL, `check_status` varchar(50) NULL DEFAULT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE, KEY `idx_device_number` (`device_number`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } stopwatchSection.Stop(); await KeepTimeLog("recreate import_niagara_item_history", stopwatchSection.ElapsedMilliseconds); #region 刪除 import_niagara_item資料表中選取的棟別 //foreach (var b in building) //{ // sql = "delete from import_niagara_item_history where device_building_tag = '" + b + "'"; // await conn.ExecuteAsync(sql); //} #endregion StringBuilder sb = new StringBuilder(); int count = 0; #region 放入import_niagara_item資料表 stopwatchSection = new Stopwatch(); stopwatchSection.Start(); string ss = string.Empty; foreach (var row in ds) { if (count == 0) { ss = @"insert import_niagara_item_history(device_number,device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_point_name, parent_path, full_name, is_history, created_at) values"; } ss += $@" ('" + row.device_number + "', '" + row.device_area_tag + "', '" + row.device_building_tag + "', '" + row.device_system_tag + "', '" + row.device_name_tag + "', '" + row.device_floor_tag + "', '" + row.device_master_tag + "', '" + row.device_last_name_tag + "', '" + row.device_serial_tag + "', '" + row.device_point_name + "', '" + row.parent_path + "', '" + row.full_name + "'," + row.isHistory + ", now() " + ")"; count++; if (count == 100) { ss += ";"; sb.Append(ss); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); ss = string.Empty; count = 0; } else ss += ","; } sb.Append(ss); if (sb.Length > 0) { sb.Clear(); ss = ss.Remove(ss.Length - 1); ss += ";"; sb.Append(ss); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sb.ToString()); } sb.Clear(); } stopwatchSection.Stop(); await KeepTimeLog("insert into import_niagara_item_history", stopwatchSection.ElapsedMilliseconds); #endregion } catch (Exception exception) { throw exception; } finally { conn.Close(); } } stopwatch.Stop(); await KeepTimeLog("InsertItemFromNiagara_History", stopwatch.ElapsedMilliseconds); } /// /// Recover device_system_tag /// /// public async Task RecoverSysTag(string tableName) { stopwatch = new Stopwatch(); stopwatch.Start(); //檢查 using (IDbConnection conn = GetDbConnection()) { conn.Open(); using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { StringBuilder sb = new StringBuilder(); sb.Append($@"SET SQL_SAFE_UPDATES = 0; update {tableName} a join variable v2 on v2.system_value = a.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3' join variable v1 on v1.id = v2.system_parent_id set a.device_system_tag = v1.system_value where a.device_system_tag is null or a.device_system_tag = '';"); await conn.ExecuteAsync(sb.ToString()); } catch (Exception exception) { throw exception; } finally { conn.Close(); } } } stopwatch.Stop(); await KeepTimeLog("RecoverSysTag", stopwatch.ElapsedMilliseconds); } /// /// record all device control point /// /// /// public async Task DeviceControlPoint(List dcp) { stopwatch = new Stopwatch(); stopwatch.Start(); using (IDbConnection conn = GetDbConnection()) { try { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_device_control_point` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(1000) DEFAULT NULL, `displayName` varchar(50) DEFAULT NULL, `device_area_tag` varchar(50) DEFAULT NULL, `device_building_tag` varchar(50) DEFAULT NULL, `device_system_tag` varchar(50) DEFAULT NULL, `device_name_tag` varchar(50) DEFAULT NULL, `device_floor_tag` varchar(50) DEFAULT NULL, `device_number` varchar(50) DEFAULT NULL, `device_point_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } stopwatchSection.Stop(); await KeepTimeLog("check and create import_niagara_device_control_point", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sql = @"truncate table import_niagara_device_control_point"; using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await conn.ExecuteAsync(sql); } stopwatchSection.Stop(); await KeepTimeLog("truncate import_niagara_device_control_point", stopwatchSection.ElapsedMilliseconds); stopwatchSection = new Stopwatch(); stopwatchSection.Start(); StringBuilder sb = new StringBuilder(); int count = 0; sql = string.Empty; foreach (var data in dcp) { if (count == 0) { sql = @"insert into import_niagara_device_control_point(name, displayName, device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_floor_tag, device_number, device_point_name) values"; } sql += $@" ('{data.name}', '{data.displayName}', '{data.device_area_tag}', '{data.device_building_tag}', '{data.device_system_tag}', '{data.device_name_tag}', '{data.device_floor_tag}', '{data.device_number}', '{data.device_point_name}')"; count++; if (count.Equals(100)) { sql += ";"; sb.Append(sql); await conn.ExecuteAsync(sb.ToString()); sb.Clear(); sql = string.Empty; count = 0; } else sql += ","; } sb.Append(sql); if (sb.Length > 0) { sb.Clear(); sql = sql.Remove(sql.Length - 1); sql += ";"; sb.Append(sql); await conn.ExecuteAsync(sb.ToString()); sb.Clear(); } var isDome = await conn.QueryFirstAsync("select system_value from variable where system_type = 'project_name'"); //巨蛋特殊處理 if (!string.IsNullOrEmpty(isDome) && isDome.Contains("ibms_dome")) { stopwatchSection = new Stopwatch(); stopwatchSection.Start(); sb.Clear(); // tag 第二碼為小類(除了安全系統之外)安全系統 第二段大類 第四段小類 sb.Append($@"update import_niagara_device_control_point a join variable b on a.device_name_tag = b.system_value COLLATE utf8mb4_0900_ai_ci and b.deleted = 0 and b.system_type = 'device_system_category_layer3' join variable v1 on b.system_parent_id = v1.id set a.device_system_tag = v1.system_value where a.device_system_tag not in ('S', 'CWB', 'B') and not (a.device_system_tag in ('FM', 'APS', 'VICL'));"); await conn.ExecuteAsync(sb.ToString()); stopwatchSection.Stop(); await KeepTimeLog("巨蛋特殊處理", stopwatchSection.ElapsedMilliseconds); } stopwatchSection.Stop(); await KeepTimeLog("insert into import_niagara_device_control_point", stopwatchSection.ElapsedMilliseconds); } catch (Exception e) { throw e; } finally { conn.Close(); } } stopwatch.Stop(); await KeepTimeLog("DeviceControlPoint", stopwatch.ElapsedMilliseconds); } public async Task KeepTimeLog(string functionName, long millisecond, [CallerLineNumber] int line = 0, [CallerMemberName] string name = "") { string path = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "Logs"); string filepath = System.IO.Path.Combine(path, "SyncLog" + DateTime.Now.ToString("yyyyMMdd") + ".txt"); using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write)) { StreamWriter sw = new StreamWriter(fs); sw.BaseStream.Seek(0, SeekOrigin.End); sw.WriteLine($"Log current time {DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}, Log function name: {functionName}, Log function usage time: {TimeSpan.FromMilliseconds(millisecond)}, Log function record line: {line}, Log called function name: {name}"); sw.WriteLine(Environment.NewLine); sw.Flush(); sw.Close(); fs.Close(); } } } }