[Backend]因應巨蛋棟同步失敗,優化同步程式

This commit is contained in:
張家睿 2025-03-28 17:13:18 +08:00
parent 85b8afb253
commit f6c1f28693

View File

@ -90,11 +90,11 @@ namespace Repository.BackendRepository.Implement
{
tag_name = x.Key.tag_name2,
displayName = x.Key.displayName2
});
});
// StringBuilder sb = new StringBuilder();
bool isDome = false; //是否為巨蛋案
int count = 0;
int count = 0;
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach (var row in ds2)
@ -125,7 +125,7 @@ namespace Repository.BackendRepository.Implement
{
if (arrTag.Length == 5)
{
isDome= true;
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
@ -209,7 +209,7 @@ namespace Repository.BackendRepository.Implement
}
}
}
/// <summary>
/// 獲取照明開關 是否在 device_node 層
/// </summary>
@ -220,9 +220,9 @@ namespace Repository.BackendRepository.Implement
stopwatch.Start();
using (IDbConnection conn = GetDbConnection())
{
conn.Open();
conn.Open();
var sql = "select system_value from variable where system_type = 'module_light_switch' ";
var module_light_switch = conn.QueryAsync<string>(sql).Result.FirstOrDefault();
var module_light_switch = conn.QueryAsync<string>(sql).Result.FirstOrDefault();
conn.Close();
stopwatch.Stop();
await KeepTimeLog("getLightSwitchLevel", stopwatch.ElapsedMilliseconds);
@ -250,7 +250,7 @@ namespace Repository.BackendRepository.Implement
{
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach(var b in building)
foreach (var b in building)
{
string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@ -281,7 +281,8 @@ namespace Repository.BackendRepository.Implement
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
ds = ds.GroupBy(x => new {
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,
@ -304,7 +305,7 @@ namespace Repository.BackendRepository.Implement
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('"+
values('" +
row.device_area_tag + "', '" +
row.device_building_tag + "', '" +
row.device_system_tag + "', '" +
@ -446,7 +447,7 @@ namespace Repository.BackendRepository.Implement
{
conn.Close();
}
}
}
@ -456,376 +457,404 @@ namespace Repository.BackendRepository.Implement
/// <returns></returns>
public async Task DeviceComparison(string LightSwitchLevel)
{
stopwatch = new Stopwatch();
stopwatch.Start();
Stopwatch stopwatch = Stopwatch.StartNew();
using (IDbConnection conn = GetDbConnection())
{
conn.Open();
try
{
List<NiagaraTags> result;
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
sb.Append($@"SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device d
WHERE m.niagara_tags = d.device_number
);");
result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("filter device item from import_niagara_tag", stopwatchSection.ElapsedMilliseconds);
// 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<NiagaraTags> niagaraTagsToAdd = (await conn.QueryAsync<NiagaraTags>(sqlGetNiagaraTags)).ToList();
sw1.Stop();
await KeepTimeLog("filter device item from import_niagara_tag", sw1.ElapsedMilliseconds);
#region device, device_kind
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
int count = 0;
//新增至device, is_link = 1
if (result.Count > 0)
// 2. 新增 device 和 device_kind
if (niagaraTagsToAdd.Count > 0)
{
var result2 = result.GroupBy(x => new
// 2.1. 新增 device
Stopwatch sw2 = Stopwatch.StartNew();
List<string> sqlInsertDeviceList = new List<string>();
foreach (var data in niagaraTagsToAdd)
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2
});
foreach (var data in result)
{
//開關控制在個別燈具(device_node層) and 小類為二線式照明系統 and tag第八段開頭不是 G
if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G")
{
// 燈具新增 device_node
continue;
}
else {
sb.Append($@" insert 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)
values(uuid(), 0, 1, 0, 1, '" +
data.device_area_tag + "', '" +
data.device_building_tag + "', '" +
data.device_system_tag + "', '" +
data.device_name_tag + "', '" +
data.device_full_name + "', '" +
data.device_floor_tag + "', '" +
data.device_master_tag + "', '" +
data.device_last_name_tag + "', '" +
data.device_serial_tag + "', '" +
data.device_model_tag + "', '" +
data.niagara_tags + "', '" +
data.device_system_tag + "', 1, now(), now() );");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
count = 0;
}
}
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)
VALUES (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());";
sqlInsertDeviceList.Add(sqlInsertDevice); // 先暫存SQL語法等等一次執行
}
if (sb.Length > 0)
// 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<object> parameters = new List<object>();
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(sb.ToString());
}
sb.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach (var data in result2)
{
var sqlString = new StringBuilder();
sqlString.Append("select * from device_kind where device_building_tag = '" + data.device_building_tag + "' and device_system_tag = '" + data.device_system_tag + "' and device_name_tag = '" + data.device_name_tag + "'");
var dk = (await conn.QueryAsync<device_kind>(sqlString.ToString())).ToList<device_kind>();
if (dk.Count == 0)
{
sb2.Append($@"INSERT 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(), '" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag +
"', 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 1);");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sb2.Clear();
count = 0;
}
await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢
scope.Complete();
}
}
if (sb2.Length > 0)
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
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sb2.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device_kind", stopwatchSection.ElapsedMilliseconds);
}
#endregion
#region device_kind process for cctv
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(@"SET SQL_SAFE_UPDATES = 0;
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 = '');");
}
stopwatchSection.Stop();
await KeepTimeLog("update cctv model is null or empty", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
var resultDeviceItem = await conn.QueryAsync<NiagaraTags>($@"select * from import_niagara_tag where device_system_tag = 'S' and device_name_tag = 'C';");
var result3 = resultDeviceItem.GroupBy(x => new
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag,
device_model_tag2 = x.device_model_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2,
device_model_tag = x.Key.device_model_tag2
});
foreach (var data in result3)
{
var sqlString = new StringBuilder();
sqlString.Append("select * from device_kind where device_building_tag = '" + data.device_building_tag + "' and device_system_tag = '" + data.device_system_tag + "' and device_name_tag = '" + data.device_name_tag + "' and device_model_tag = '" + data.device_model_tag + "'");
var dk = (await conn.QueryAsync<device_kind>(sqlString.ToString())).ToList<device_kind>();
if (dk.Count == 0)
x.device_building_tag,
x.device_system_tag,
x.device_name_tag
}).Select(g => new
{
sb2.Append($@"INSERT 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(), '" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag +
"', 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), '" + data.device_model_tag + "', 1);");
count += 1;
if (count >= 100)
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<bool>(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(sb2.ToString());
await conn.ExecuteAsync(sqlInsertDeviceKind, parameters2); // 使用參數化查詢
scope.Complete();
}
sb2.Clear();
count = 0;
}
}
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<NiagaraTags>(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<bool>(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();
}
}
}
if (sb2.Length > 0)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sw5.Stop();
await KeepTimeLog("insert cctv device_kind", sw5.ElapsedMilliseconds);
sb2.Clear();
}
// 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($@"SET SQL_SAFE_UPDATES = 0;
UPDATE device_kind dk
left JOIN (
SELECT device_system_tag, device_name_tag, device_model_tag
FROM import_niagara_tag
LIMIT 100000
) i ON dk.device_system_tag = i.device_system_tag
and dk.device_name_tag = i.device_name_tag
and dk.device_model_tag = i.device_model_tag
SET dk.is_link = 0
WHERE dk.is_link = 1 and dk.device_system_tag = 'S' and dk.device_name_tag = 'C' and i.device_system_tag is null;");
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($@"SET SQL_SAFE_UPDATES = 0;
UPDATE device_kind dk
left JOIN (
SELECT device_system_tag, device_name_tag, device_model_tag
FROM import_niagara_tag
LIMIT 100000
) i ON dk.device_system_tag = i.device_system_tag
and dk.device_name_tag = i.device_name_tag
and dk.device_model_tag = i.device_model_tag
SET dk.is_link = 1
WHERE dk.is_link = 0 and dk.device_system_tag = 'S' and dk.device_name_tag = 'C' and i.device_system_tag is not null;");
await conn.ExecuteAsync(sqlUpdateDeviceKindIsLinkToOne); // 使用參數化查詢
scope.Complete();
}
stopwatchSection.Stop();
await KeepTimeLog("insert/update cctv model is_link", stopwatchSection.ElapsedMilliseconds);
#endregion
#region device_node
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
sb.Append($@" SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device_node d
WHERE m.niagara_tags COLLATE utf8mb4_0900_ai_ci = d.device_number COLLATE utf8mb4_0900_ai_ci
);");
result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
sb.Clear();
sw6.Stop();
await KeepTimeLog("insert/update cctv model is_link", sw6.ElapsedMilliseconds);
if (result.Count > 0)
// 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<NiagaraTags> niagaraTagsToAddForNode = (await conn.QueryAsync<NiagaraTags>(sqlGetNiagaraTagsForNode)).ToList();
if (niagaraTagsToAddForNode.Count > 0)
{
var result2 = result.GroupBy(x => new
// 4.1. 新增 device_node
List<string> sqlInsertDeviceNodeList = new List<string>();
foreach (var data in niagaraTagsToAddForNode)
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2
});
count = 0;
foreach (var data in result)
{
//開關控制在個別燈具(device_node層) and 小類為二線式照明系統 and tag第八段開頭不是 G
if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G")
{
// 燈具新增 device_node
sb.Append($@"INSERT INTO device_node(device_node_guid, deleted, device_guid, device_number, full_name, created_by, created_at, updated_at)
VALUES (uuid(), 0, '' " + //device_guid 父層需要 forge 那邊提供
",'" + data.niagara_tags + // device_number
"', '" + data.device_full_name + //full_name
"','B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), now());");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
count = 0;
}
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);
}
}
if (sb.Length > 0)
//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<object> parameters = new List<object>();
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(sb.ToString());
await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢
scope.Complete();
}
sb.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device_node", stopwatchSection.ElapsedMilliseconds);
}
#endregion
sw7.Stop();
await KeepTimeLog("insert into device_node", sw7.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
//device有niagara有is_link 更新成 1
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device d
JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) 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(sb.ToString());
}
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("update device is_link = 1, deleted = 0", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
//device有niagara沒有is_link 更新成 0
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device d
left JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) i ON d.device_number = i.niagara_tags
SET d.is_link = 0
WHERE d.is_link = 1 and i.niagara_tags is null;");
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("update device is_link = 0", stopwatchSection.ElapsedMilliseconds);
// 5. 更新 device 的 is_link
Stopwatch sw8 = Stopwatch.StartNew();
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
// device_node 有, niagara沒有, is_link 更新成 0
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device_node dn
left JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) i ON dn.device_number COLLATE utf8mb4_0900_ai_ci = i.niagara_tags COLLATE utf8mb4_0900_ai_ci
SET dn.is_link = 0
WHERE dn.is_link = 1 and i.niagara_tags is null;");
// 先更新 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(sb.ToString());
await conn.ExecuteAsync(sqlUpdateDeviceIsLinkToOne); // 使用參數化查詢
scope.Complete();
}
stopwatchSection.Stop();
await KeepTimeLog("update device_node is_link = 0", stopwatchSection.ElapsedMilliseconds);
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 exception;
throw;
throw; // 保留原始堆疊追蹤
}
finally
{
conn.Close();
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
}
}
@ -1335,7 +1364,7 @@ namespace Repository.BackendRepository.Implement
throw exception;
}
finally
{
{
conn.Close();
}
}
@ -1356,7 +1385,8 @@ namespace Repository.BackendRepository.Implement
try
{
StringBuilder sb = new StringBuilder();
sb.Append("update device set full_name=device_number where full_Name='';");
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)
@ -1424,17 +1454,13 @@ namespace Repository.BackendRepository.Implement
{
StringBuilder sb = new StringBuilder();
sb.Append(@"SET SQL_SAFE_UPDATES = 0;
update device d
JOIN (
select niagara_tags, device_full_name from import_niagara_tag limit 100000
) m ON m.niagara_tags = d.device_number
LEFT JOIN (
SELECT niagara_tags, device_full_name
FROM import_niagara_tag
LIMIT 100000
) m2 ON m2.niagara_tags = d.device_number AND m2.device_full_name = d.full_name
SET d.full_name = m.device_full_name
WHERE m2.niagara_tags IS NULL;");
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)
@ -1591,7 +1617,7 @@ namespace Repository.BackendRepository.Implement
conn.Close();
}
}
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
// 過濾 dv 集合,只保留設備編號有效的項目
@ -1959,7 +1985,7 @@ SET FOREIGN_KEY_CHECKS = 1;";
/// </summary>
/// <param name="dcp"></param>
/// <returns></returns>
public async Task DeviceControlPoint (List<DeviceControlPoint> dcp)
public async Task DeviceControlPoint(List<DeviceControlPoint> dcp)
{
stopwatch = new Stopwatch();
stopwatch.Start();