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