From 91602a95c6816b9221f8085650c76123c4c336fb Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Wed, 21 May 2025 17:11:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0IoTDB=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E8=A1=A8=E6=A8=A1=E5=9E=8B=E5=BB=BA=E8=A1=A8=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E5=A4=84=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 102 ++++++----- .../Attributes/IgnoreInitTableAttribute.cs | 14 ++ .../Interface/IIoTDBProvider.cs | 17 +- .../Interface/IIoTDBSessionPool.cs | 7 + .../JiShe.CollectBus.IoTDB/Model/IoTEntity.cs | 2 +- .../Model/TableModelSingleMeasuringEntity.cs | 1 + .../Provider/IoTDBProvider.cs | 162 +++++++++++++++++- .../Provider/SessionPoolAdapter.cs | 18 +- .../Provider/TableSessionPoolAdapter.cs | 18 +- .../Samples/SampleAppService.cs | 35 +++- .../BasicScheduledMeterReadingService.cs | 2 + .../Devices/DeviceTableModelDataInfo.cs | 3 +- .../Devices/DeviceTreeModelDataInfo.cs | 4 +- .../Helpers/CommonHelper.cs | 67 ++++++++ 14 files changed, 381 insertions(+), 71 deletions(-) create mode 100644 modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 00a7129..c0ce66c 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -348,44 +348,58 @@ namespace JiShe.CollectBus.IncrementalGenerator private static string BuildFactoryCode() { return """ - using System; - using System.Collections.Concurrent; - using System.Reflection; + using System; + using System.Collections.Concurrent; + using System.Reflection; - namespace JiShe.CollectBus.Analyzers.Shared; + namespace JiShe.CollectBus.Analyzers.Shared; - public static class SourceEntityAccessorFactory - { - private static readonly ConcurrentDictionary _accessors = new(); - - public static ISourceEntityAccessor GetAccessor() + public static class SourceEntityAccessorFactory { - return (ISourceEntityAccessor)_accessors.GetOrAdd(typeof(T), t => + private static readonly ConcurrentDictionary _accessors = new(); + + public static ISourceEntityAccessor GetAccessor() { - // 获取泛型类型定义信息(如果是泛型类型) - var isGeneric = t.IsGenericType; - var genericTypeDef = isGeneric ? t.GetGenericTypeDefinition() : null; - var arity = isGeneric ? genericTypeDef!.GetGenericArguments().Length : 0; - - // 构建访问器类名 - var typeName = isGeneric - ? $"{t.Namespace}.{genericTypeDef!.Name.Split('`')[0]}Accessor`{arity}" - : $"{t.Namespace}.{t.Name}Accessor"; - - // 尝试从当前程序集加载 - var accessorType = Assembly.GetAssembly(t)!.GetType(typeName) - ?? throw new InvalidOperationException($"Accessor type {typeName} not found"); - - // 处理泛型参数 - if (isGeneric && accessorType.IsGenericTypeDefinition) + return (ISourceEntityAccessor)_accessors.GetOrAdd(typeof(T), t => { - accessorType = accessorType.MakeGenericType(t.GetGenericArguments()); - } + // 获取泛型类型定义信息(如果是泛型类型) + var isGeneric = t.IsGenericType; + var genericTypeDef = isGeneric ? t.GetGenericTypeDefinition() : null; + var arity = isGeneric ? genericTypeDef!.GetGenericArguments().Length : 0; - return Activator.CreateInstance(accessorType)!; - }); + // 构建访问器类名 + var typeName = isGeneric + ? $"{t.Namespace}.{genericTypeDef!.Name.Split('`')[0]}Accessor`{arity}" + : $"{t.Namespace}.{t.Name}Accessor"; + + // 尝试从当前程序集加载 + var accessorType = Assembly.GetAssembly(t)!.GetType(typeName) + ?? throw new InvalidOperationException($"Accessor type {typeName} not found"); + + // 处理泛型参数 + if (isGeneric && accessorType.IsGenericTypeDefinition) + { + accessorType = accessorType.MakeGenericType(t.GetGenericArguments()); + } + + return Activator.CreateInstance(accessorType)!; + }); + } + + public static object GetAccessor(Type type) + { + MethodInfo getAccessorMethod = typeof(SourceEntityAccessorFactory) + .GetMethod( + name: nameof(GetAccessor), + bindingAttr: BindingFlags.Public | BindingFlags.Static, + + types: Type.EmptyTypes + ); + + MethodInfo genericMethod = getAccessorMethod.MakeGenericMethod(type); + return genericMethod.Invoke(null, null); + } } - } """; } @@ -531,8 +545,8 @@ namespace JiShe.CollectBus.IncrementalGenerator var entityType = prop.ContainingType.ToDisplayString();//entity 实体类型名称 var propType = prop.Type;//实体属性的类型 var propTypeName = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - // var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32") - // 处理可空类型,获取底层具体类型名称 + // var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32") + // 处理可空类型,获取底层具体类型名称 var declaredTypeName = propType switch { INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } nullableType => @@ -583,19 +597,19 @@ namespace JiShe.CollectBus.IncrementalGenerator $"GetValueTupleElementDeclaredTypeName(typeof({elementType})), " +//$"\"{elementDeclaredName}\", " + $"(e) => Get{prop.Name}_{elementName}(({entityType})e), " + $"(e, v) => Set{prop.Name}_{elementName}(({entityType})e, ({elementType})v))"); - } - } - } + } + } + } - code.AppendLine(string.Join(",\n", initializerLines)); - code.AppendLine(" };"); + code.AppendLine(string.Join(",\n", initializerLines)); + code.AppendLine(" };"); - code.AppendLine(GetValueTupleElementName()); - } + code.AppendLine(GetValueTupleElementName()); + } - private static string GetValueTupleElementName() - { - return """ + private static string GetValueTupleElementName() + { + return """ public static string GetValueTupleElementDeclaredTypeName(Type declaredType) { string typeName; @@ -613,7 +627,7 @@ namespace JiShe.CollectBus.IncrementalGenerator return typeName; } """; - } + } private static string GenerateAttributeInitializer(AttributeData attribute) diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs new file mode 100644 index 0000000..bd6006c --- /dev/null +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/IgnoreInitTableAttribute.cs @@ -0,0 +1,14 @@ +namespace JiShe.CollectBus.IoTDB.Attributes +{ + /// + /// 需要忽略表模型初始化,有此特性无需初始化 + /// + [AttributeUsage(AttributeTargets.Class)] + public class IgnoreInitTableAttribute : System.Attribute + { + + public IgnoreInitTableAttribute() + { + } + } +} diff --git a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs index a5d885d..08454b2 100644 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBProvider.cs @@ -10,12 +10,11 @@ namespace JiShe.CollectBus.IoTDB.Interface /// public interface IIoTDbProvider { - ///// - ///// 切换 SessionPool - ///// - ///// 是否使用表模型 - //void SwitchSessionPool(bool useTableSession); - + /// + /// 切换 SessionPool + /// + /// 是否使用表模型 + /// IIoTDbProvider GetSessionPool(bool sessionpolType); /// @@ -66,5 +65,11 @@ namespace JiShe.CollectBus.IoTDB.Interface /// /// Task> QueryAsync(IoTDBQueryOptions options) where T : IoTEntity, new(); + + /// + /// 初始化表模型 + /// + /// + Task InitTableSessionModelAsync(); } } diff --git a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs index 6bcbc5c..d183099 100644 --- a/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs +++ b/modules/JiShe.CollectBus.IoTDB/Interface/IIoTDBSessionPool.cs @@ -32,5 +32,12 @@ namespace JiShe.CollectBus.IoTDB.Interface /// /// Task ExecuteQueryStatementAsync(string sql); + + /// + /// 执行无返回结果SQL + /// + /// + /// + Task ExecuteNonQueryStatementAsync(string sql); } } diff --git a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs index da14d20..a8163d8 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs @@ -50,7 +50,7 @@ namespace JiShe.CollectBus.IoTDB.Model /// private string _devicePath; /// - /// 设备路径 + /// 设备路径,树模型使用,表模型会在数据插入的时候直接获取继承类的名称作为表明 /// public virtual string DevicePath { diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index 376b677..89ea088 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -7,6 +7,7 @@ namespace JiShe.CollectBus.IoTDB.Model /// Table模型单项数据实体 /// [SourceAnalyzers(EntityTypeEnum.TableModel)] + [IgnoreInitTable] public class TableModelSingleMeasuringEntity : IoTEntity { /// diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs index cd57ea9..e89bbc8 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs @@ -26,6 +26,8 @@ using System.Diagnostics.Metrics; using Newtonsoft.Json.Linq; using static System.Runtime.InteropServices.JavaScript.JSType; using System.Text.RegularExpressions; +using System.Xml.Linq; +using System.Linq; namespace JiShe.CollectBus.IoTDB.Provider { @@ -366,6 +368,10 @@ namespace JiShe.CollectBus.IoTDB.Provider { tableNameOrTreePath = metadata.TableNameOrTreePath; } + else if(metadata.IsSingleMeasuring && string.IsNullOrWhiteSpace(metadata.TableNameOrTreePath) == true)//单侧点时,且路径没有指定,取默认实体名称和第一个列名组合。 + { + tableNameOrTreePath = $"{metadata.EntityName}_{metadata.ColumnNames.First()}"; + } else { tableNameOrTreePath = DevicePathBuilder.GetTableName(); @@ -630,10 +636,7 @@ namespace JiShe.CollectBus.IoTDB.Provider { // 过滤元组子项 if (member.NameOrPath.Contains(".Item")) continue; - - // 类型名称处理 - string declaredTypeName = member.DeclaredTypeName; - + // 特性查询优化 var attributes = member.CustomAttributes ?? Enumerable.Empty(); var tagAttr = attributes.OfType().FirstOrDefault(); @@ -842,6 +845,25 @@ namespace JiShe.CollectBus.IoTDB.Provider } } + /// + /// 处理不同列类型的逻辑 + /// + /// + /// + private string ProcessCategory(IReadOnlyDictionary> groupedColumns, ColumnCategory category) + { + if (groupedColumns.TryGetValue(category, out var cols)) + { + List tempColumnInfos = new List(); + foreach (var item in cols) + { + tempColumnInfos.Add($" {item.Name} {item.DataType} {item.Category}"); + } + return string.Join(",", tempColumnInfos); + } + return string.Empty; + } + /// /// 数据列结构 /// @@ -976,6 +998,136 @@ namespace JiShe.CollectBus.IoTDB.Provider return cache; } - private static readonly Regex _asciiAlphanumericRegex = new Regex(@"^[a-zA-Z0-9]*$", RegexOptions.Compiled); + + + /// + /// 初始化表模型 + /// + /// + public async Task InitTableSessionModelAsync() + { + //获取JiShe.CollectBus.IoTDB程序集和JiShe.CollectBus.Domain程序集中的所有 [SourceAnalyzers(EntityTypeEnum.TableModel)] 的实体 + var assemblyNames = new[] { "JiShe.CollectBus.IoTDB", "JiShe.CollectBus.Domain" }; + var assemblies = CommonHelper.LoadAssemblies(assemblyNames); + + var targetTypes = CollectTargetTypes(assemblies); + if (targetTypes == null || targetTypes.Count <= 0) + { + _logger.LogError($"{nameof(InitTableSessionModelAsync)} 初始化表模型时没有找到对应的实体类信息。"); + return; + } + +// @"CREATE TABLE table1( +// time TIMESTAMP TIME, +// region STRING TAG, +// plant_id STRING TAG, +// device_id STRING TAG, +// model_id STRING ATTRIBUTE, +// maintenance STRING ATTRIBUTE, +// temperature FLOAT FIELD, +// humidity FLOAT FIELD, +// status Boolean FIELD, +// arrival_time TIMESTAMP FIELD +//) COMMENT 'table1' WITH(TTL = 31536000000);"; + + + foreach (var item in targetTypes) + { + var accessor = SourceEntityAccessorFactory.GetAccessor(item); + //通过 dynamic 简化操作 + dynamic dynamicAccessor = accessor; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("CREATE TABLE IF NOT EXISTS "); + stringBuilder.Append(dynamicAccessor.EntityName); + stringBuilder.Append("( time TIMESTAMP TIME, "); + var columns = new List(); + foreach (var member in dynamicAccessor.MemberList) + { + // 过滤元组子项 + if (member.NameOrPath.Contains(".Item")) continue; + + // 特性查询优化 + var attributes = (IEnumerable)(member.CustomAttributes ?? Enumerable.Empty()); + var tagAttr = attributes.OfType().FirstOrDefault(); + var attrColumn = attributes.OfType().FirstOrDefault(); + var fieldColumn = attributes.OfType().FirstOrDefault(); + + // 构建ColumnInfo + ColumnInfo? column = null; + if (tagAttr != null) + { + column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName); + } + else if (attrColumn != null) + { + column = new ColumnInfo(member.NameOrPath, ColumnCategory.ATTRIBUTE, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName); + } + else if (fieldColumn != null) + { + column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(member.DeclaredTypeName), false, member.DeclaredTypeName); + } + + if (!column.HasValue) + { + _logger.LogError($"{nameof(InitTableSessionModelAsync)} 初始化表模型时实体类{dynamicAccessor.EntityName}的{member.NameOrPath}列的ColumnInfo构建失败。"); + continue; + } + columns.Add(column.Value); + } + + //按业务逻辑顺序处理(TAG -> ATTRIBUTE -> FIELD) + var groupedColumns = columns + .GroupBy(c => c.Category) + .ToDictionary(g => g.Key, g => g.ToList()); + List tempColumInfos = new List(); + + tempColumInfos.Add( ProcessCategory(groupedColumns, ColumnCategory.TAG)); + tempColumInfos.Add(ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE)); + tempColumInfos.Add(ProcessCategory(groupedColumns, ColumnCategory.FIELD)); + stringBuilder.Append(string.Join(",", tempColumInfos.Where(d => !string.IsNullOrWhiteSpace(d)))); + stringBuilder.Append($" ) COMMENT '{item.Name}' "); + + _logger.LogError($"{dynamicAccessor.EntityName} 初始化语句:{stringBuilder.ToString()}"); + + await CurrentSession.ExecuteNonQueryStatementAsync($"{stringBuilder.ToString()}"); + } + + } + + + /// + /// 获取程序集中的所有 [SourceAnalyzers(EntityTypeEnum.TableModel)] 的实体 + /// + /// + /// + private List CollectTargetTypes(List assemblies) + { + var targetTypes = new List(); + foreach (var assembly in assemblies) + { + try + { + foreach (var type in assembly.GetExportedTypes()) + { + //获取表模型特性的类 + var sourceAnalyzersAttribute = type.GetCustomAttribute(); + + //需要忽略表模型初始化,有此特性无需初始化 + var ignoreInitTableAttribute = type.GetCustomAttribute(); + + if (sourceAnalyzersAttribute?.EntityType == EntityTypeEnum.TableModel && ignoreInitTableAttribute == null) + { + if (type.GetConstructor(Type.EmptyTypes) != null) + targetTypes.Add(type); + } + } + } + catch (ReflectionTypeLoadException ex) + { + _logger.LogError($"加载 {assembly} 失败: {string.Join(", ", ex.LoaderExceptions.Select(e => e.Message))}"); + } + } + return targetTypes; + } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs index 26ea4c7..a6d2cf5 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/SessionPoolAdapter.cs @@ -71,8 +71,7 @@ namespace JiShe.CollectBus.IoTDB.Provider if (result != 0) { throw new Exception($"{nameof(SessionPoolAdapter)} Tree模型数据入库没有成功,返回结果为:{result},请检查IoTEntity继承子类属性索引是否有变动。"); - } - //await CloseAsync(); + } return result; } @@ -83,9 +82,18 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public async Task ExecuteQueryStatementAsync(string sql) { - var result = await _sessionPool.ExecuteQueryStatementAsync(sql, _options.Timeout); - //await result.Close(); - //await CloseAsync(); + var result = await _sessionPool.ExecuteQueryStatementAsync(sql, _options.Timeout); + return result; + } + + /// + /// 执行无返回结果SQL + /// + /// + /// + public async Task ExecuteNonQueryStatementAsync(string sql) + { + var result = await _sessionPool.ExecuteNonQueryStatementAsync(sql); return result; } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs b/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs index 8edb112..5708de6 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/TableSessionPoolAdapter.cs @@ -70,8 +70,7 @@ namespace JiShe.CollectBus.IoTDB.Provider { throw new Exception($"{nameof(TableSessionPoolAdapter)} table模型数据入库没有成功,返回结果为:{result},请检查IoTEntity继承子类属性索引是否有变动。"); } - - //await CloseAsync(); + return result; } @@ -82,9 +81,18 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public async Task ExecuteQueryStatementAsync(string sql) { - var result = await _sessionPool.ExecuteQueryStatementAsync(sql,_options.Timeout); - //await result.Close(); - //await CloseAsync(); + var result = await _sessionPool.ExecuteQueryStatementAsync(sql,_options.Timeout); + return result; + } + + /// + /// 执行无返回结果SQL + /// + /// + /// + public async Task ExecuteNonQueryStatementAsync(string sql) + { + var result = await _sessionPool.ExecuteNonQueryStatementAsync(sql); return result; } diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index 40c2db2..c6340ed 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -30,6 +30,7 @@ using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.Metrics; using System.Threading.Tasks; using TouchSocket.Core; using TouchSocket.Sockets; @@ -173,7 +174,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS }; await _iotDBProvider.InsertAsync(meter2); - + ElectricityMeter meter3 = new ElectricityMeter() { @@ -207,7 +208,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS time = DateTime.Now; //System.Reflection.PropertyInfo; //System.Reflection.FieldInfo - //TreeModelSingleMeasuringEntityAccessor + //TreeModelSingleMeasuringEntityAccessor var meter = new TreeModelSingleMeasuringEntity() { SystemName = "energy", @@ -585,5 +586,35 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS await Task.CompletedTask; } + + + /// + /// IoTDB空表查询情况 + /// + /// + [HttpGet] + public async Task TestIoTDBEmptyTableQuery() + { + var meter = new MeterReadingTelemetryPacketInfo() { DevicePath = "MeterReadingTelemetryPacketInfo", DeviceId = "1111" }; + QueryCondition conditions = new QueryCondition() + { + Field = "DeviceId", + Operator = "=", + Value = meter.DeviceId + }; + var query = new IoTDBQueryOptions() + { + TableNameOrTreePath = meter.DevicePath, + PageIndex = 1, + PageSize = 1, + Conditions = new List() { conditions }, + }; + + await _iotDBProvider.GetSessionPool(true).InitTableSessionModelAsync(); + + var pageResult = await _iotDBProvider.GetSessionPool(true).QueryAsync(query); + + await Task.CompletedTask; + } } diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index e4a8843..5ec68a6 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -329,6 +329,8 @@ namespace JiShe.CollectBus.ScheduledMeterReading // 创建取消令牌源 //var cts = new CancellationTokenSource(); + await _dbProvider.GetSessionPool(true).InitTableSessionModelAsync(); + _ = _dataChannelManage.ScheduledMeterTaskReadingAsync(DataChannelManage.TaskDataChannel.Reader); // //此处代码不要删除 diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs index 4ced50b..c909930 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTableModelDataInfo.cs @@ -13,7 +13,8 @@ namespace JiShe.CollectBus.IotSystems.Devices /// 设备表型数据信息 /// [SourceAnalyzers(EntityTypeEnum.TableModel)] - public class DeviceTreeModelDataInfo: IoTEntity + [IgnoreInitTable] + public class DeviceTableModelDataInfo : IoTEntity { [FIELDColumn] diff --git a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs index 27a59c7..9fcb850 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/Devices/DeviceTreeModelDataInfo.cs @@ -12,8 +12,8 @@ namespace JiShe.CollectBus.IotSystems.Devices /// /// 设备树模型数据信息 /// - [SourceAnalyzers(EntityTypeEnum.TableModel)] - public class DeviceTableModelDataInfo : IoTEntity + [SourceAnalyzers(EntityTypeEnum.TreeModel)] + public class DeviceTreeModelDataInfo : IoTEntity { [FIELDColumn] diff --git a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs b/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs index a7a65c6..7c7ef1f 100644 --- a/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs +++ b/shared/JiShe.CollectBus.Common/Helpers/CommonHelper.cs @@ -865,5 +865,72 @@ namespace JiShe.CollectBus.Common.Helpers return Convert.ToInt64(scoresStr); } + + /// + /// 加载指定名称的程序集 + /// + /// + /// + public static List LoadAssemblies(string[] assemblyNames) + { + var assemblies = new List(); + + // 获取已加载的程序集 + foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) + { + if (assemblyNames.Contains(asm.GetName().Name)) + assemblies.Add(asm); + } + + // 尝试加载未加载的程序集 + foreach (var name in assemblyNames) + { + if (!assemblies.Any(a => a.GetName().Name == name)) + { + try + { + var assembly = Assembly.Load(name); + assemblies.Add(assembly); + } + catch (FileNotFoundException) + { + // 若Load失败,尝试从基目录加载 + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{name}.dll"); + if (File.Exists(path)) + { + try + { + assemblies.Add(Assembly.LoadFrom(path)); + } + catch { /* 记录错误 */ } + } + } + } + } + + return assemblies; + } + + /// + /// 创建类型实例 + /// + /// + /// + public static List CreateInstances(List types) + { + var instances = new List(); + foreach (var type in types) + { + try + { + instances.Add(Activator.CreateInstance(type)); + } + catch (Exception) + { + throw; + } + } + return instances; + } } }