using System; using System.Collections.Concurrent; using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Reflection; using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading.Tasks; using Apache.IoTDB; using Apache.IoTDB.DataStructure; using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Helpers; using JiShe.CollectBus.Common.Models; using JiShe.CollectBus.IoTDB.Attributes; using JiShe.CollectBus.IoTDB.Context; using JiShe.CollectBus.IoTDB.Interface; using JiShe.CollectBus.IoTDB.Model; using JiShe.CollectBus.IoTDB.Options; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities; using JiShe.CollectBus.Analyzers.Shared; using JiShe.CollectBus.IoTDB.Exceptions; using System.Diagnostics.Metrics; using Newtonsoft.Json.Linq; using static System.Runtime.InteropServices.JavaScript.JSType; using System.Text.RegularExpressions; namespace JiShe.CollectBus.IoTDB.Provider { /// /// IoTDB数据源 /// public class IoTDbProvider : IIoTDbProvider, ITransientDependency { private static readonly ConcurrentDictionary MetadataCache = new(); private readonly ILogger _logger; private readonly IIoTDbSessionFactory _sessionFactory; private readonly IoTDBRuntimeContext _runtimeContext; private IIoTDbSessionPool CurrentSession => _sessionFactory.GetSessionPool(_runtimeContext.UseTableSessionPool); /// /// IoTDbProvider /// /// /// /// public IoTDbProvider( ILogger logger, IIoTDbSessionFactory sessionFactory, IoTDBRuntimeContext runtimeContext) { _logger = logger; _sessionFactory = sessionFactory; _runtimeContext = runtimeContext; } /// /// 插入数据 /// /// /// /// public async Task InsertAsync(T entity) where T : IoTEntity { try { var metadata = await GetMetadata(); var tablet = BuildTablet(new[] { entity }, metadata); if (tablet == null || tablet.Count <= 0) { _logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null"); return; } await CurrentSession.InsertAsync(tablet.First()); } catch (Exception ex) { _logger.LogError(ex, $"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时发生异常"); throw; } } /// /// 批量插入数据 /// /// /// public async Task BatchInsertAsync(IEnumerable entities) where T : IoTEntity { try { var metadata = await GetMetadata(); var batchSize = 1000; var batches = entities.Chunk(batchSize); foreach (var batch in batches) { var tablet = BuildTablet(batch, metadata); if (tablet == null || tablet.Count <= 0) { _logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null"); return; } foreach (var item in tablet) { await CurrentSession.InsertAsync(item); } } } catch (Exception ex) { _logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常"); throw; } } /// /// 批量插入数据 /// /// /// 设备元数据 /// /// public async Task BatchInsertAsync(DeviceMetadata deviceMetadata, IEnumerable entities) where T : IoTEntity { try { var batchSize = 2000; var batches = entities.Chunk(batchSize); foreach (var batch in batches) { var tablet = BuildTablet(batch, deviceMetadata); if (tablet == null || tablet.Count <= 0) { _logger.LogError($"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时 tablet 为null"); return; } foreach (var item in tablet) { await CurrentSession.InsertAsync(item); } } } catch (Exception ex) { _logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常"); throw; } } /// /// 删除数据 /// /// /// /// public async Task DeleteAsync(IoTDBQueryOptions options) where T : IoTEntity { try { var query = await BuildDeleteSQL(options); var result = await CurrentSession.ExecuteQueryStatementAsync(query); if (result == null) { return 0; } if (!result.HasNext()) { _logger.LogWarning($"{typeof(T).Name} IoTDB删除{typeof(T).Name}的数据时,没有返回受影响记录数量。"); return 0; } //获取唯一结果行 var row = result.Next(); await result.Close(); var dataResult = row.Values[0]; return dataResult; } catch (Exception ex) { _logger.LogError(ex, $"{nameof(DeleteAsync)} IoTDB删除{typeof(T).Name}的数据时发生异常"); throw; } } /// /// 获取设备元数据 /// /// /// public async Task GetMetadata() where T : IoTEntity { var accessor = SourceEntityAccessorFactory.GetAccessor(); var columns = CollectColumnMetadata(accessor); var tmpMetadata = BuildDeviceMetadata(columns, accessor); string tableNameOrTreePath = string.Empty; var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute(); if (tableNameOrTreePathAttribute != null) { tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath; } tmpMetadata.EntityName = accessor.EntityName; tmpMetadata.EntityType = accessor.EntityType; tmpMetadata.TableNameOrTreePath = tableNameOrTreePath; var metaData = MetadataCache.AddOrUpdate( typeof(T), addValueFactory: t => tmpMetadata, // 如果键不存在,用此值添加 updateValueFactory: (t, existingValue) => { var columns = CollectColumnMetadata(accessor); var metadata = BuildDeviceMetadata(columns, accessor); //对现有值 existingValue 进行修改,返回新值 string tableNameOrTreePath = string.Empty; var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute(); if (tableNameOrTreePathAttribute != null) { tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath; } existingValue.ColumnNames = metadata.ColumnNames; existingValue.DataTypes = metadata.DataTypes; return existingValue; } ); //var metaData = MetadataCache.GetOrAdd(typeof(T), type => //{ // var columns = CollectColumnMetadata(accessor); // var metadata = BuildDeviceMetadata(columns, accessor); // string tableNameOrTreePath = string.Empty; // var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute(); // if (tableNameOrTreePathAttribute != null) // { // tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath; // } // metadata.EntityName = accessor.EntityName; // metadata.EntityType = accessor.EntityType; // metadata.TableNameOrTreePath = tableNameOrTreePath; // return metadata; //}); return await Task.FromResult(metaData); } /// /// 查询数据 /// /// /// /// public async Task> QueryAsync(IoTDBQueryOptions options) where T : IoTEntity, new() { try { var stopwatch2 = Stopwatch.StartNew(); var query = await BuildQuerySQL(options); var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query); var result = new BusPagedResult { TotalCount = await GetTotalCount(options), Items = await ParseResults(sessionDataSet, options.PageSize), PageIndex = options.PageIndex, PageSize = options.PageSize, }; stopwatch2.Stop(); //int totalPageCount = (int)Math.Ceiling((double)result.TotalCount / options.PageSize); if (result.Items.Count() < result.PageSize) { result.HasNext = false; } else { result.HasNext = true; } //result.HasNext = result.Items.Count() > 0 ? result.Items.Count() < result.PageSize : false; return result; } catch (Exception ex) { CurrentSession.Dispose(); _logger.LogError(ex, $"{nameof(QueryAsync)} IoTDB查询{typeof(T).Name}的数据时发生异常"); throw; } } /// /// 构建Tablet /// /// /// 表实体 /// 设备元数据 /// private List BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity { var entitiyList = entities.ToList(); if (entitiyList == null || entitiyList.Count <= 0) { return null; } //var accessor = SourceEntityAccessorFactory.GetAccessor(); //var memberCache = BuildMemberCache(accessor); if (metadata.EntityType == null) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101"); } if (metadata.EntityType == EntityTypeEnum.Other) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 不属于IoTDB数据模型实体,属于异常情况,-102"); } if (metadata.EntityType == EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103"); } else if (metadata.EntityType == EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104"); } string tableNameOrTreePath = string.Empty; if (_runtimeContext.UseTableSessionPool)//表模型 { //如果指定了路径 if (!string.IsNullOrWhiteSpace(metadata.TableNameOrTreePath)) { tableNameOrTreePath = metadata.TableNameOrTreePath; } else { tableNameOrTreePath = DevicePathBuilder.GetTableName(); } return new List() { BuildTablet(entitiyList, metadata, tableNameOrTreePath) }; } else { //树模型的时候,实体的设备Id可能会不同,因此需要根据不同路径进行存储。 var tabletList = new List(); var groupEntities = entitiyList.GroupBy(d => d.DevicePath).ToList(); foreach (var group in groupEntities) { tabletList.Add(BuildTablet(group.ToList(), metadata, group.Key)); } return tabletList; } } private Tablet BuildTablet(List entities, DeviceMetadata metadata, string tableNameOrTreePath) where T : IoTEntity { // 预分配内存结构 var rowCount = entities.Count; var timestamps = new long[rowCount]; var values = new object[rowCount][]; for (var i = 0; i < values.Length; i++) { values[i] = new object[metadata.ColumnNames.Count]; } List tempColumnNames = new List(); tempColumnNames.AddRange(metadata.ColumnNames); // 顺序处理数据(保证线程安全) for (var row = 0; row < rowCount; row++) { var entity = entities[row]; timestamps[row] = entity.Timestamps; for (int i = 0; i < metadata.ColumnNames.Count; i++) { var processor = metadata.Processors[i]; if (processor.IsSingleMeasuring) { tempColumnNames[i] = (string)processor.SingleMeasuringNameGetter(entity); } // 获取并转换值 values[row][i] = processor.ValueGetter(entity); } } return _runtimeContext.UseTableSessionPool ? BuildTableSessionTablet(metadata, tableNameOrTreePath, tempColumnNames, values.Select(d => d.ToList()).ToList(), timestamps.ToList()) : BuildSessionTablet(metadata, tableNameOrTreePath, tempColumnNames, values.Select(d => d.ToList()).ToList(), timestamps.ToList()); } /// /// 构建tree模型的Tablet /// /// 已解析的设备数据元数据 /// 设备路径 /// 数据列集合 /// 数据集合 /// 时间戳集合 /// private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List columns, List> values, List timestamps) { //todo 树模型需要去掉TAG类型和ATTRIBUTE类型的字段,只需要保留FIELD类型字段即可 return new Tablet( devicePath, columns, metadata.DataTypes, values, timestamps ); } /// /// 构建表模型的Tablet /// /// 已解析的设备数据元数据 /// 表名称 /// 数据列集合 /// 数据集合 /// 时间戳集合 /// private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List columns, List> values, List timestamps) { var tablet = new Tablet( tableName, columns, metadata.ColumnCategories, metadata.DataTypes, values, timestamps ); return tablet; } /// /// 构建查询语句 /// /// /// /// private async Task BuildQuerySQL(IoTDBQueryOptions options) where T : IoTEntity { var metadata = await GetMetadata(); var sb = new StringBuilder("SELECT "); sb.AppendJoin(", ", metadata.ColumnNames); sb.Append($" FROM {options.TableNameOrTreePath}"); if (options.Conditions.Any()) { sb.Append(" WHERE "); sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition)); } sb.Append($" LIMIT {options.PageSize} OFFSET {options.PageIndex * options.PageSize}"); return sb.ToString(); } /// /// 构建删除语句 /// /// /// /// private async Task BuildDeleteSQL(IoTDBQueryOptions options) where T : IoTEntity { var metadata = await GetMetadata(); var sb = new StringBuilder(); if (!_runtimeContext.UseTableSessionPool) { sb.Append("DELETE "); } else { sb.Append("DROP "); } sb.Append($" FROM {options.TableNameOrTreePath}"); sb.AppendJoin(", ", metadata.ColumnNames); if (options.Conditions.Any()) { sb.Append(" WHERE "); sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition)); } return sb.ToString(); } /// /// 将查询条件转换为SQL语句 /// /// /// /// private string TranslateCondition(QueryCondition condition) { return condition.Operator switch { ">" => condition.IsNumber ? $"{condition.Field} > {condition.Value}" : $"{condition.Field} > '{condition.Value}'", "<" => condition.IsNumber ? $"{condition.Field} < {condition.Value}" : $"{condition.Field} < '{condition.Value}'", "=" => condition.IsNumber ? $"{condition.Field} = {condition.Value}" : $"{condition.Field} = '{condition.Value}'", _ => throw new NotSupportedException($"{nameof(TranslateCondition)} 将查询条件转换为SQL语句时操作符 {condition.Operator} 属于异常情况") }; } /// /// 获取查询条件的总数量 /// /// /// /// private async Task GetTotalCount(IoTDBQueryOptions options) where T : IoTEntity { var countQuery = $"SELECT COUNT(*) FROM {options.TableNameOrTreePath}"; if (options.Conditions.Any()) { countQuery += " WHERE " + string.Join(" AND ", options.Conditions.Select(TranslateCondition)); } var result = await CurrentSession.ExecuteQueryStatementAsync(countQuery); if (result == null) { return 0; } if (!result.HasNext()) { return 0; } var count = Convert.ToInt32(result.Next().Values[0]); await result.Close(); return count; } /// /// 解析查询结果 /// /// /// /// /// private async Task> ParseResults(SessionDataSet dataSet, int pageSize) where T : IoTEntity, new() { var results = new List(); var metadata = await GetMetadata(); var accessor = SourceEntityAccessorFactory.GetAccessor(); var memberCache = BuildMemberCache(accessor); while (dataSet.HasNext() && results.Count < pageSize) { var record = dataSet.Next(); var entity = new T { Timestamps = record.Timestamps }; for (int i = 0; i < metadata.Processors.Count; i++) { var value = record.Values[i]; metadata.Processors[i].ValueSetter(entity, value); } results.Add(entity); } await dataSet.Close(); return results; } /// /// 获取设备元数据的列 /// /// /// private List CollectColumnMetadata(ISourceEntityAccessor accessor) { var columns = new List(); var memberCache = BuildMemberCache(accessor); foreach (var member in accessor.MemberList) { // 过滤元组子项 if (member.NameOrPath.Contains(".Item")) continue; // 类型名称处理 Type declaredType = member.DeclaredType; var underlyingType = Nullable.GetUnderlyingType(declaredType); string declaredTypeName = underlyingType?.Name ?? member.DeclaredTypeName; // 特性查询优化 var attributes = member.CustomAttributes ?? Enumerable.Empty(); var tagAttr = attributes.OfType().FirstOrDefault(); var attrColumn = attributes.OfType().FirstOrDefault(); var fieldColumn = attributes.OfType().FirstOrDefault(); var singleMeasuringAttr = attributes.OfType().FirstOrDefault(); // 构建ColumnInfo ColumnInfo? column = null; if (tagAttr != null) { column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(declaredTypeName), false, member.DeclaredTypeName); } else if (attrColumn != null) { column = new ColumnInfo(member.NameOrPath, ColumnCategory.ATTRIBUTE, GetDataTypeFromTypeName(declaredTypeName), false, member.DeclaredTypeName); } else if (fieldColumn != null) { column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(declaredTypeName), false, member.DeclaredTypeName); } // 单测模式处理 if (singleMeasuringAttr != null && column == null) { var tupleItemKey = $"{member.NameOrPath}.Item2"; if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember)) { throw new Exception($"{nameof(CollectColumnMetadata)} {accessor.EntityName} {member.NameOrPath} 单侧点属性解析异常"); } column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(tupleMember.DeclaredTypeName), true, tupleMember.DeclaredTypeName); } if (column.HasValue) columns.Add(column.Value); } return columns; } /// /// 构建设备元数据 /// /// 待解析的类 /// 已处理好的数据列 /// private DeviceMetadata BuildDeviceMetadata(List columns, ISourceEntityAccessor accessor) where T : IoTEntity { var metadata = new DeviceMetadata(); //先检查是不是单侧点模型 if (columns.Any(c => c.IsSingleMeasuring)) { metadata.IsSingleMeasuring = true; } //按业务逻辑顺序处理(TAG -> ATTRIBUTE -> FIELD) var groupedColumns = columns .GroupBy(c => c.Category) .ToDictionary(g => g.Key, g => g.ToList()); ProcessCategory(groupedColumns, ColumnCategory.TAG, metadata); ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE, metadata); ProcessCategory(groupedColumns, ColumnCategory.FIELD, metadata); // 新增处理器初始化 foreach (var item in metadata.ColumnNames) { ColumnInfo column = columns.FirstOrDefault(d => d.Name == item); var processor = new ColumnProcessor { ColumnName = column.Name, IsSingleMeasuring = column.IsSingleMeasuring, GetConverter = GetterConverter(column.DeclaredTypeName.ToUpper()), SetConverter = SetterConverter(column.Name.ToUpper()), TSDataType = column.DataType, }; // 处理单测点 if (column.IsSingleMeasuring) { var item1Member = accessor.MemberList .First(m => m.NameOrPath == $"{column.Name}.Item1"); processor.SingleMeasuringNameGetter = (obj) => { // 获取原始值并转为字符串 object rawValue = item1Member.Getter(obj); string value = rawValue?.ToString(); ValidateSingleMeasuringName(value); return value; }; var item2Member = accessor.MemberList .First(m => m.NameOrPath == $"{column.Name}.Item2"); processor.ValueGetter = (obj) => { object rawValue = item2Member.Getter(obj); return processor.GetConverter(rawValue); }; } else { // 获取对应的成员访问器 var member = accessor.MemberList.First(m => m.NameOrPath == column.Name); processor.ValueGetter = (obj) => { object rawValue = member.Getter(obj); return processor.GetConverter(rawValue); }; //对应的属性成员进行赋值 processor.ValueSetter = (obj, value) => { dynamic tempValue = GetTSDataValue(processor.TSDataType, value); var rawValue = processor.SetConverter(value); member.Setter(obj, rawValue); }; } metadata.Processors.Add(processor); } return metadata; } /// /// 验证单测点名称格式 /// private void ValidateSingleMeasuringName(string value) { if (string.IsNullOrWhiteSpace(value)) { return; } // 规则1: 严格检查ASCII字母和数字(0-9, A-Z, a-z) bool hasInvalidChars = value.Any(c => !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))); // 规则2: 首字符不能是数字 bool startsWithDigit = value[0] >= '0' && value[0] <= '9'; // 规则3: 全字符串不能都是数字 bool allDigits = value.All(c => c >= '0' && c <= '9'); // 按优先级抛出具体异常 if (hasInvalidChars) { throw new InvalidOperationException( $"SingleMeasuring name '{value}' 包含非法字符,只允许字母和数字"); } else if (startsWithDigit) { throw new InvalidOperationException( $"SingleMeasuring name '{value}' 不能以数字开头"); } else if (allDigits) { throw new InvalidOperationException( $"SingleMeasuring name '{value}' 不能全为数字"); } } /// /// 取值的处理器 /// /// /// private Func GetterConverter(string declaredTypeName) { return declaredTypeName switch { "DATETIME" => value => ((DateTime)value).GetDateTimeOffset().ToUnixTimeNanoseconds(), _ => value => value }; } /// /// 设置值的处理 /// /// /// private Func SetterConverter(string columnName) => columnName.ToLower().EndsWith("time") ? value => new DateTime(Convert.ToInt64(value), DateTimeKind.Utc) : value => value; /// /// 处理不同列类型的逻辑 /// /// /// /// private void ProcessCategory(IReadOnlyDictionary> groupedColumns, ColumnCategory category, DeviceMetadata metadata) { if (groupedColumns.TryGetValue(category, out var cols)) { metadata.ColumnNames.AddRange(cols.Select(c => c.Name)); metadata.ColumnCategories.AddRange(cols.Select(c => c.Category)); metadata.DataTypes.AddRange(cols.Select(c => c.DataType)); } } /// /// 数据列结构 /// private readonly struct ColumnInfo { /// /// 列名 /// public string Name { get; } /// /// 声明的类型的名称 /// public string DeclaredTypeName { get; } /// /// 是否是单测点 /// public bool IsSingleMeasuring { get; } /// /// 列类型 /// public ColumnCategory Category { get; } /// /// 数据类型 /// public TSDataType DataType { get; } public ColumnInfo(string name, ColumnCategory category, TSDataType dataType, bool isSingleMeasuring, string declaredTypeName) { Name = name; Category = category; DataType = dataType; IsSingleMeasuring = isSingleMeasuring; DeclaredTypeName = declaredTypeName; } } /// /// 根据类型名称获取对应的 IoTDB 数据类型 /// /// 类型名称(不区分大小写) /// 对应的 TSDataType,默认返回 TSDataType.STRING private TSDataType GetDataTypeFromTypeName(string typeName) { if (string.IsNullOrWhiteSpace(typeName)) return TSDataType.STRING; return DataTypeMap.TryGetValue(typeName.Trim(), out var dataType) ? dataType : TSDataType.STRING; } /// /// 根据类型名称获取 IoTDB 数据类型 /// private readonly IReadOnlyDictionary DataTypeMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["BOOLEAN"] = TSDataType.BOOLEAN, ["INT32"] = TSDataType.INT32, ["INT64"] = TSDataType.INT64, ["FLOAT"] = TSDataType.FLOAT, ["DOUBLE"] = TSDataType.DOUBLE, ["TEXT"] = TSDataType.TEXT, ["NULLTYPE"] = TSDataType.NONE, ["DATETIME"] = TSDataType.TIMESTAMP, ["DATE"] = TSDataType.DATE, ["BLOB"] = TSDataType.BLOB, ["DECIMAL"] = TSDataType.STRING, ["STRING"] = TSDataType.STRING }; /// /// 根据类型名称获取 IoTDB 数据默认值 /// private readonly IReadOnlyDictionary DataTypeDefaultValueMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["BOOLEAN"] = false, ["INT32"] = 0, ["INT64"] = 0, ["FLOAT"] = 0.0f, ["DOUBLE"] = 0.0d, ["TEXT"] = string.Empty, ["NULLTYPE"] = null, ["DATETIME"] = null, ["DATE"] = null, ["BLOB"] = null, ["DECIMAL"] = "0.0", ["STRING"] = string.Empty }; /// /// IoTDB 数据类型与.net类型映射 /// /// /// /// private dynamic GetTSDataValue(TSDataType tSDataType, object value) => tSDataType switch { TSDataType.BOOLEAN => Convert.ToBoolean(value), TSDataType.INT32 => Convert.ToInt32(value), TSDataType.INT64 => Convert.ToInt64(value), TSDataType.FLOAT => Convert.ToDouble(value), TSDataType.DOUBLE => Convert.ToDouble(value), TSDataType.TEXT => Convert.ToString(value), TSDataType.NONE => null, TSDataType.TIMESTAMP => Convert.ToInt64(value), TSDataType.DATE => Convert.ToDateTime(value), TSDataType.BLOB => Convert.ToByte(value), TSDataType.STRING => Convert.ToString(value), _ => Convert.ToString(value) }; /// /// 缓存实体属性信息 /// /// /// /// private Dictionary BuildMemberCache(ISourceEntityAccessor accessor) { var cache = new Dictionary(StringComparer.Ordinal); foreach (var member in accessor.MemberList) { cache[member.NameOrPath] = member; } return cache; } private static readonly Regex _asciiAlphanumericRegex = new Regex(@"^[a-zA-Z0-9]*$", RegexOptions.Compiled); } }