完善IOTDB Provider封装
This commit is contained in:
parent
e1d4126db0
commit
5772ce906d
@ -25,15 +25,14 @@ public class SampleAppService : CollectBusAppService, ISampleAppService
|
|||||||
ElectricityMeter meter = new ElectricityMeter()
|
ElectricityMeter meter = new ElectricityMeter()
|
||||||
{
|
{
|
||||||
SystemName = "Energy",
|
SystemName = "Energy",
|
||||||
DeviceId = "402440506"
|
DeviceId = "402440506",
|
||||||
,
|
|
||||||
DeviceType = "Ammeter",
|
DeviceType = "Ammeter",
|
||||||
Current = 10,
|
Current = 10,
|
||||||
MeterModel = "DDZY-1980",
|
MeterModel = "DDZY-1980",
|
||||||
ProjectCode = "10059",
|
ProjectCode = "10059",
|
||||||
Voltage = 10
|
Voltage = 10
|
||||||
};
|
};
|
||||||
await _iotDBProvider.InsertAsync(meter);
|
await _iotDBProvider.InsertAsync(meter,2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<SampleDto> GetAsync()
|
public Task<SampleDto> GetAsync()
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Common.AttributeInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 排序序号
|
||||||
|
/// </summary>
|
||||||
|
public class NumericalOrderAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 序号
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 排序序号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
public NumericalOrderAttribute(int index)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/JiShe.CollectBus.Common/Extensions/EnumExtensions.cs
Normal file
68
src/JiShe.CollectBus.Common/Extensions/EnumExtensions.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class EnumExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将枚举转换为<string, int>字典
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEnum"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<string, int> ToDictionary<TEnum>() where TEnum : Enum
|
||||||
|
{
|
||||||
|
return Enum.GetValues(typeof(TEnum))
|
||||||
|
.Cast<TEnum>()
|
||||||
|
.ToDictionary(
|
||||||
|
e => e.ToString(),
|
||||||
|
e => Convert.ToInt32(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将枚举转换为<string, int>字典
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEnum"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<string, TEnum> ToEnumDictionary<TEnum>() where TEnum : Enum
|
||||||
|
{
|
||||||
|
return Enum.GetValues(typeof(TEnum))
|
||||||
|
.Cast<TEnum>()
|
||||||
|
.ToDictionary(
|
||||||
|
e => e.ToString(),
|
||||||
|
e => e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将枚举转换为<int, string>字典
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEnum"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<int, string> ToValueNameDictionary<TEnum>() where TEnum : Enum
|
||||||
|
{
|
||||||
|
return Enum.GetValues(typeof(TEnum))
|
||||||
|
.Cast<TEnum>()
|
||||||
|
.ToDictionary(
|
||||||
|
e => Convert.ToInt32(e),
|
||||||
|
e => e.ToString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将枚举转换为<TEnum, string>字典
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEnum"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<TEnum, string> ToEnumNameDictionary<TEnum>() where TEnum : Enum
|
||||||
|
{
|
||||||
|
return Enum.GetValues(typeof(TEnum))
|
||||||
|
.Cast<TEnum>()
|
||||||
|
.ToDictionary(
|
||||||
|
e => e,
|
||||||
|
e => e.ToString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
764
src/JiShe.CollectBus.Common/Helpers/CommonHelper.cs
Normal file
764
src/JiShe.CollectBus.Common/Helpers/CommonHelper.cs
Normal file
@ -0,0 +1,764 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JiShe.CollectBus.Common.AttributeInfo;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class CommonHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得无符号GUID
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetGUID()
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString("N");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取时间戳
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="isSeconds">是否返回秒,false返回毫秒</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static long GetTimeStampTen(bool isSeconds)
|
||||||
|
{
|
||||||
|
if (isSeconds)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定长度的随机数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetRandomNumber(int length = 8)
|
||||||
|
{
|
||||||
|
if (length <= 8)
|
||||||
|
{
|
||||||
|
length = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > 31)
|
||||||
|
{
|
||||||
|
length = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
var randomArray = RandomNumberGenerator.GetBytes(length);
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
foreach (var item in randomArray)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.ToString().Substring(0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C#反射遍历对象属性获取键值对
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">对象类型</typeparam>
|
||||||
|
/// <param name="model">对象</param>
|
||||||
|
public static Dictionary<string, object> GetClassProperties<T>(T model)
|
||||||
|
{
|
||||||
|
Type t = model.GetType();
|
||||||
|
List<PropertyInfo> propertyList = new List<PropertyInfo>();
|
||||||
|
|
||||||
|
PropertyInfo[] tempPropertyList = t.GetProperties();
|
||||||
|
if (tempPropertyList != null && tempPropertyList.Length > 0)
|
||||||
|
{
|
||||||
|
propertyList.AddRange(tempPropertyList);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentPropertyInfo = t.BaseType?.GetProperties();
|
||||||
|
if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in parentPropertyInfo)
|
||||||
|
{
|
||||||
|
if (!propertyList.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理
|
||||||
|
{
|
||||||
|
propertyList.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, object> resultData = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
foreach (PropertyInfo item in propertyList)
|
||||||
|
{
|
||||||
|
resultData.Add(item.Name, item.GetValue(model, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C#反射遍历对象属性,将键值对赋值给属性
|
||||||
|
/// </summary>
|
||||||
|
public static object SetClassProperties(string typeModel, Dictionary<string, object> keyValues)
|
||||||
|
{
|
||||||
|
if (keyValues.Count <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type tType = Type.GetType(typeModel);
|
||||||
|
|
||||||
|
|
||||||
|
PropertyInfo[] PropertyList = tType.GetProperties();
|
||||||
|
|
||||||
|
object objModel = tType.Assembly.CreateInstance(tType.FullName);
|
||||||
|
foreach (PropertyInfo item in PropertyList)
|
||||||
|
{
|
||||||
|
if (keyValues.ContainsKey(item.Name))
|
||||||
|
{
|
||||||
|
object objectValue = keyValues[item.Name];
|
||||||
|
item.SetValue(objModel, objectValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return objModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取得某月的第一天
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datetime">要取得月份第一天的时间</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static DateTime FirstDayOfMonth(this DateTime datetime)
|
||||||
|
{
|
||||||
|
return datetime.AddDays(1 - datetime.Day);
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 取得某月的最后一天
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datetime">要取得月份最后一天的时间</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static DateTime LastDayOfMonth(this DateTime datetime)
|
||||||
|
{
|
||||||
|
return datetime.AddDays(1 - datetime.Day).AddMonths(1).AddDays(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取得某月第一天0点以及最后一天的23:59:59时间范围
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datetime"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Tuple<DateTime, DateTime> GetMonthDateRange(this DateTime datetime)
|
||||||
|
{
|
||||||
|
var lastDayOfMonthDate = LastDayOfMonth(datetime);
|
||||||
|
return new Tuple<DateTime, DateTime>(datetime.FirstDayOfMonth(), new DateTime(lastDayOfMonthDate.Year, lastDayOfMonthDate.Month, lastDayOfMonthDate.Day, 23, 59, 59));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取得某一天0点到当月最后一天的23:59:59时间范围
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datetime"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Tuple<DateTime, DateTime> GetCurrentDateToLastDayRange(this DateTime datetime)
|
||||||
|
{
|
||||||
|
var lastDayOfMonthDate = LastDayOfMonth(datetime);
|
||||||
|
return new Tuple<DateTime, DateTime>(datetime.Date, new DateTime(lastDayOfMonthDate.Year, lastDayOfMonthDate.Month, lastDayOfMonthDate.Day, 23, 59, 59));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取得某一天0点到23:59:59时间范围
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datetime"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Tuple<DateTime, DateTime> GetCurrentDateRange(this DateTime datetime)
|
||||||
|
{
|
||||||
|
return new Tuple<DateTime, DateTime>(datetime.Date, new DateTime(datetime.Year, datetime.Month, datetime.Day, 23, 59, 59));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定枚举的所有 Attribute 说明以及value组成的键值对
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">对象类</param>
|
||||||
|
/// <param name="getPropertie">false获取字段、true获取属性</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<SelectResult> GetEnumAttributeList(Type type, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SelectResult> selectResults = new List<SelectResult>();
|
||||||
|
List<MemberInfo> memberInfos = new List<MemberInfo>();
|
||||||
|
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
FieldInfo[] fieldArray = type.GetFields();
|
||||||
|
if (null == fieldArray || fieldArray.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInfos.AddRange(fieldArray);
|
||||||
|
//获取父类的字段
|
||||||
|
var parentFieldInfo = type.BaseType?.GetFields();
|
||||||
|
if (parentFieldInfo != null && parentFieldInfo.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in parentFieldInfo)
|
||||||
|
{
|
||||||
|
if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理
|
||||||
|
{
|
||||||
|
memberInfos.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PropertyInfo[] properties = type.GetProperties();
|
||||||
|
if (null == properties || properties.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInfos.AddRange(properties);
|
||||||
|
//获取父类的属性
|
||||||
|
var parentPropertyInfo = type.BaseType?.GetProperties();
|
||||||
|
if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in parentPropertyInfo)
|
||||||
|
{
|
||||||
|
if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理
|
||||||
|
{
|
||||||
|
memberInfos.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in memberInfos)
|
||||||
|
{
|
||||||
|
DescriptionAttribute[] EnumAttributes =
|
||||||
|
(DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
|
||||||
|
dynamic infoObject = null;
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
infoObject = (FieldInfo)item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoObject = (PropertyInfo)item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnumAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
SelectResult selectResult = new SelectResult()
|
||||||
|
{
|
||||||
|
Key = Convert.ToInt32(infoObject.GetValue(null)).ToString(),
|
||||||
|
Value = EnumAttributes[0].Description,
|
||||||
|
};
|
||||||
|
|
||||||
|
selectResults.Add(selectResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayAttribute[] DisplayAttributes =
|
||||||
|
(DisplayAttribute[])item.GetCustomAttributes(typeof(DisplayAttribute), false);
|
||||||
|
if (DisplayAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
SelectResult selectResult =
|
||||||
|
selectResults.FirstOrDefault(e => e.Key == Convert.ToInt32(infoObject.GetValue(null)).ToString());
|
||||||
|
if (selectResult != null)
|
||||||
|
{
|
||||||
|
selectResult.SecondValue = DisplayAttributes[0].Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定枚举的所有 Attribute 说明以及value组成的键值对
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">对象类</param>
|
||||||
|
/// <param name="thirdAttributeType">第三个标签类型</param>
|
||||||
|
/// <param name="thirdAttributePropertieName">第三个标签类型取值名称</param>
|
||||||
|
/// <param name="getPropertie">false获取字段、true获取属性</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<SelectResult> GetEnumAttributeListWithThirdValue(Type type, Type thirdAttributeType, string thirdAttributePropertieName, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SelectResult> selectResults = new List<SelectResult>();
|
||||||
|
List<MemberInfo> memberInfos = new List<MemberInfo>();
|
||||||
|
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
FieldInfo[] EnumInfo = type.GetFields();
|
||||||
|
if (null == EnumInfo || EnumInfo.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
memberInfos.AddRange(EnumInfo);
|
||||||
|
var parentFieldInfo = type.BaseType?.GetFields();
|
||||||
|
if (parentFieldInfo != null && parentFieldInfo.Length > 0)
|
||||||
|
{
|
||||||
|
memberInfos.AddRange(parentFieldInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PropertyInfo[] EnumInfo = type.GetProperties();
|
||||||
|
if (null == EnumInfo || EnumInfo.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
memberInfos.AddRange(EnumInfo);
|
||||||
|
var parentPropertyInfo = type.BaseType?.GetProperties();
|
||||||
|
if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
|
||||||
|
{
|
||||||
|
memberInfos.AddRange(parentPropertyInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in memberInfos)
|
||||||
|
{
|
||||||
|
var thirdAttributes = item.
|
||||||
|
GetCustomAttributes(thirdAttributeType, false);
|
||||||
|
if (thirdAttributes == null || thirdAttributes.Length <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[])item.
|
||||||
|
GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
|
||||||
|
dynamic infoObject = null;
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
infoObject = (FieldInfo)item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoObject = (PropertyInfo)item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptionAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
SelectResult selectResult = new SelectResult()
|
||||||
|
{
|
||||||
|
Key = infoObject.Name,
|
||||||
|
Value = descriptionAttributes[0].Description,
|
||||||
|
};
|
||||||
|
|
||||||
|
selectResults.Add(selectResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayAttribute[] displayAttributes = (DisplayAttribute[])item.
|
||||||
|
GetCustomAttributes(typeof(DisplayAttribute), false);
|
||||||
|
if (displayAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name);
|
||||||
|
if (selectResult != null)
|
||||||
|
{
|
||||||
|
selectResult.SecondValue = displayAttributes[0].Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thirdAttributes.Length > 0 && !string.IsNullOrWhiteSpace(thirdAttributePropertieName))
|
||||||
|
{
|
||||||
|
foreach (var attr in thirdAttributes)
|
||||||
|
{
|
||||||
|
// 使用反射获取特性的属性值
|
||||||
|
var properties = thirdAttributeType.GetProperties();
|
||||||
|
foreach (var prop in properties)
|
||||||
|
{
|
||||||
|
// 假设你要获取特性的某个属性值,例如 TypeName
|
||||||
|
if (prop.Name == thirdAttributePropertieName)
|
||||||
|
{
|
||||||
|
object value = prop.GetValue(attr);
|
||||||
|
SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name);
|
||||||
|
if (selectResult != null)
|
||||||
|
{
|
||||||
|
selectResult.ThirdValue = value?.ToString(); // 将属性值赋给 ThirdValue
|
||||||
|
}
|
||||||
|
break; // 如果找到了需要的属性,可以跳出循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类、指定常量值的Description说明
|
||||||
|
/// 包含直接继承的父级字段
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t">对象类</param>
|
||||||
|
/// <param name="getPropertie"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<Tuple<string, string, int>> GetTypeDescriptionListToTuple(Type t, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (t == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MemberInfo> memberInfos = new List<MemberInfo>();
|
||||||
|
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
FieldInfo[] fieldInfo = t.GetFields();
|
||||||
|
if (null == fieldInfo || fieldInfo.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInfos.AddRange(fieldInfo);
|
||||||
|
var parentFieldInfo = t.BaseType?.GetFields();
|
||||||
|
if (parentFieldInfo != null && parentFieldInfo.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in parentFieldInfo)
|
||||||
|
{
|
||||||
|
if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理
|
||||||
|
{
|
||||||
|
memberInfos.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PropertyInfo[] fieldInfo = t.GetProperties();
|
||||||
|
if (null == fieldInfo || fieldInfo.Length <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInfos.AddRange(fieldInfo);
|
||||||
|
var parentPropertyInfo = t.BaseType?.GetProperties();
|
||||||
|
if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in parentPropertyInfo)
|
||||||
|
{
|
||||||
|
if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段,跳过不处理
|
||||||
|
{
|
||||||
|
memberInfos.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Tuple<string, string, int>> tuples = new List<Tuple<string, string, int>>();
|
||||||
|
|
||||||
|
foreach (var item in memberInfos)
|
||||||
|
{
|
||||||
|
DescriptionAttribute[] descriptionAttribute =
|
||||||
|
(DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
|
||||||
|
NumericalOrderAttribute[] indexAttributes =
|
||||||
|
(NumericalOrderAttribute[])item.GetCustomAttributes(typeof(NumericalOrderAttribute), false);
|
||||||
|
|
||||||
|
|
||||||
|
if (descriptionAttribute.Length > 0 && indexAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
Tuple<string, string, int> tuple = new Tuple<string, string, int>(item.Name,
|
||||||
|
descriptionAttribute[0].Description, indexAttributes[0].Index);
|
||||||
|
tuples.Add(tuple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tuples;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类、指定常量值的常量说明
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fieldName">常量字段名称</param>
|
||||||
|
///<param name="getPropertie">属性还是字段</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetTypeDescriptionName<T>(string fieldName, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(fieldName))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberInfo memberInfo = null;
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
memberInfo = typeof(T).GetField(fieldName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memberInfo = typeof(T).GetProperty(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == memberInfo)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptionAttribute[] EnumAttributes =
|
||||||
|
(DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
if (EnumAttributes.Length <= 0)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return EnumAttributes[0].Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定命名空间下指定常量值的常量说明
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fieldName">常量字段名称</param>
|
||||||
|
/// <param name="assemblyName">命名空间,主要用来找到对应程序集</param>
|
||||||
|
///<param name="getPropertie">属性还是字段</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetTypeDescriptionName(string fieldName, string assemblyName, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(fieldName) || string.IsNullOrWhiteSpace(assemblyName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string desc = "";
|
||||||
|
foreach (var item in GetEnumList(assemblyName))
|
||||||
|
{
|
||||||
|
desc = GetTypeDescriptionName(item, fieldName, getPropertie);
|
||||||
|
if (!string.IsNullOrEmpty(desc))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类、指定常量值的常量说明
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t">对象类</param>
|
||||||
|
/// <param name="fieldName">常量字段名称</param>
|
||||||
|
///<param name="getPropertie">属性还是字段</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetTypeDescriptionName(this Type t, string fieldName, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(fieldName))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberInfo memberInfo = null;
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
memberInfo = t.GetField(fieldName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memberInfo = t.GetProperty(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != memberInfo)
|
||||||
|
{
|
||||||
|
DescriptionAttribute[] EnumAttributes =
|
||||||
|
(DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
|
if (EnumAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
return EnumAttributes[0].Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扩展方法,获得枚举值集合
|
||||||
|
///</summary>
|
||||||
|
///<returns>枚举的DisplayName</returns>
|
||||||
|
public static List<T> GetEnumList<T>() where T : Enum
|
||||||
|
{
|
||||||
|
List<T> enumList = new List<T>();
|
||||||
|
foreach (T value in Enum.GetValues(typeof(T)))
|
||||||
|
{
|
||||||
|
enumList.Add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Type> GetEnumList(string assemblyName)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(assemblyName))
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.Load(assemblyName);
|
||||||
|
List<Type> ts = assembly.GetTypes().Where(x => x.GetTypeInfo().IsClass).ToList();
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<Type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扩展方法,获得枚举的Display值
|
||||||
|
///</summary>
|
||||||
|
///<param name="value">枚举值</param>
|
||||||
|
///<param name="nameInstead">当枚举值没有定义DisplayNameAttribute,是否使用枚举名代替,默认是使用</param>
|
||||||
|
///<param name="getPropertie">属性还是字段</param>
|
||||||
|
///<returns>枚举的DisplayName</returns>
|
||||||
|
public static string GetDisplayName(this Enum value, Boolean nameInstead = true, bool getPropertie = false)
|
||||||
|
{
|
||||||
|
Type type = value.GetType();
|
||||||
|
string name = Enum.GetName(type, value);
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayAttribute attribute = null;
|
||||||
|
|
||||||
|
if (getPropertie == false)
|
||||||
|
{
|
||||||
|
attribute = Attribute.GetCustomAttribute(type.GetField(name), typeof(DisplayAttribute)) as DisplayAttribute;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attribute =
|
||||||
|
Attribute.GetCustomAttribute(type.GetProperty(name), typeof(DisplayAttribute)) as DisplayAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (attribute == null && nameInstead == true)
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attribute == null ? null : attribute.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取枚举的描述信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetEnumDescription(this Enum value)
|
||||||
|
{
|
||||||
|
var name = value.ToString();
|
||||||
|
var field = value.GetType().GetField(name);
|
||||||
|
if (field == null) return name;
|
||||||
|
|
||||||
|
var att = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute), false);
|
||||||
|
|
||||||
|
return att == null ? field.Name : ((DescriptionAttribute)att).Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将传入的字符串中间部分字符替换成特殊字符
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">需要替换的字符串</param>
|
||||||
|
/// <param name="startLen">前保留长度</param>
|
||||||
|
/// <param name="endLen">尾保留长度</param>
|
||||||
|
/// <param name="specialChar">特殊字符</param>
|
||||||
|
/// <returns>被特殊字符替换的字符串</returns>
|
||||||
|
public static string ReplaceWithSpecialChar(this string value, int startLen = 1, int endLen = 1,
|
||||||
|
char specialChar = '*')
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (value.Length <= startLen + endLen)
|
||||||
|
{
|
||||||
|
var temStartVal = value.Substring(0, startLen);
|
||||||
|
return $"{temStartVal}{"".PadLeft(endLen, specialChar)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Length == 10 && endLen == 1)
|
||||||
|
{
|
||||||
|
endLen = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
var startVal = value.Substring(0, startLen);
|
||||||
|
var endVal = value.Substring(value.Length - endLen);
|
||||||
|
if (value.Length == 2)
|
||||||
|
{
|
||||||
|
endVal = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = $"{startVal}{endVal.PadLeft(value.Length - startLen, specialChar)}";
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Linux下字体名称转换
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fontValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetLinuxFontFamily(this string fontValue)
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
if (fontValue == "楷体")
|
||||||
|
{
|
||||||
|
fontValue = "KaiTi";
|
||||||
|
}
|
||||||
|
else if (fontValue == "隶书")
|
||||||
|
{
|
||||||
|
fontValue = "LiSu";
|
||||||
|
}
|
||||||
|
else if (fontValue == "宋体")
|
||||||
|
{
|
||||||
|
fontValue = "SimSun";
|
||||||
|
}
|
||||||
|
else if (fontValue == "微软雅黑")
|
||||||
|
{
|
||||||
|
fontValue = "Microsoft YaHei";
|
||||||
|
}
|
||||||
|
else if (fontValue == "新宋体")
|
||||||
|
{
|
||||||
|
fontValue = "NSimSun";
|
||||||
|
}
|
||||||
|
else if (fontValue == "仿宋")
|
||||||
|
{
|
||||||
|
fontValue = "FangSong";
|
||||||
|
}
|
||||||
|
else if (fontValue == "黑体")
|
||||||
|
{
|
||||||
|
fontValue = "SimHei";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return fontValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -123,4 +123,32 @@ namespace JiShe.CollectBus.Common.Helpers
|
|||||||
writer.WriteStringValue(value.ToString(_dateFormatString));
|
writer.WriteStringValue(value.ToString(_dateFormatString));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unix格式时间格式化
|
||||||
|
/// </summary>
|
||||||
|
public class UnixTimeConverter : JsonConverter<DateTime>
|
||||||
|
{
|
||||||
|
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
if (long.TryParse(reader.GetString(), out long timestamp))
|
||||||
|
return DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonTokenType.Number)
|
||||||
|
{
|
||||||
|
long timestamp = reader.GetInt64();
|
||||||
|
return DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
|
||||||
|
}
|
||||||
|
return reader.GetDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
long timestamp = new DateTimeOffset(value).ToUnixTimeSeconds();
|
||||||
|
writer.WriteStringValue(timestamp.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/JiShe.CollectBus.Common/Helpers/SelectResult.cs
Normal file
35
src/JiShe.CollectBus.Common/Helpers/SelectResult.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace JiShe.CollectBus.Common.Helpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉框选项元素
|
||||||
|
/// </summary>
|
||||||
|
public class SelectResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉框 键
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉框 值
|
||||||
|
/// </summary>
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉框 值2
|
||||||
|
/// </summary>
|
||||||
|
public string SecondValue { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下拉框 值3
|
||||||
|
/// </summary>
|
||||||
|
public object ThirdValue { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,16 +16,27 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="entity"></param>
|
/// <param name="entity"></param>
|
||||||
|
/// <param name="buildTabletMode">构建表模型方式,1 根据实体《T》直接显示指定Tag,2根据实体《T》的名称指定表名</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task InsertAsync<T>(T entity) where T : IoTEntity;
|
Task InsertAsync<T>(T entity, int buildTabletMode) where T : IoTEntity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 批量插入数据
|
/// 批量插入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="entities"></param>
|
/// <param name="entities"></param>
|
||||||
|
/// <param name="buildTabletMode">构建表模型方式,1 根据实体《T》直接显示指定Tag,2根据实体《T》的名称指定表名</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task BatchInsertAsync<T>(IEnumerable<T> entities) where T : IoTEntity;
|
Task BatchInsertAsync<T>(IEnumerable<T> entities, int buildTabletMode) where T : IoTEntity;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除数据
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<object> DeleteAsync<T>(QueryOptions options) where T : IoTEntity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询数据
|
/// 查询数据
|
||||||
|
|||||||
@ -10,4 +10,7 @@
|
|||||||
<PackageReference Include="Apache.IoTDB" Version="2.0.1" />
|
<PackageReference Include="Apache.IoTDB" Version="2.0.1" />
|
||||||
<PackageReference Include="Volo.Abp" Version="8.3.3" />
|
<PackageReference Include="Volo.Abp" Version="8.3.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -11,6 +11,11 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class QueryOptions
|
public class QueryOptions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名或标签名
|
||||||
|
/// </summary>
|
||||||
|
public required string TableNameOrTagName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分页
|
/// 分页
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -13,17 +13,17 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
public class DeviceMetadata
|
public class DeviceMetadata
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 测量值集合,用于构建Table的测量值,也就是field参数
|
/// 测量值集合,用于构建Table的测量值,也就是columnNames参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Measurements { get; } = new();
|
public List<string> ColumnNames { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 列类型集合,用于构建Table的列类型,也就是columnCategory参数
|
/// 列类型集合,用于构建Table的列类型,也就是columnCategories参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ColumnCategory> ColumnCategories { get; } = new();
|
public List<ColumnCategory> ColumnCategories { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 值类型集合,用于构建Table的值类型,也就是dataType参数
|
/// 值类型集合,用于构建Table的值类型,也就是dataTypes参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<TSDataType>DataTypes { get; } = new();
|
public List<TSDataType>DataTypes { get; } = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
using Apache.IoTDB;
|
using Apache.IoTDB;
|
||||||
using Apache.IoTDB.DataStructure;
|
using Apache.IoTDB.DataStructure;
|
||||||
|
using JiShe.CollectBus.Common.Extensions;
|
||||||
|
using JiShe.CollectBus.Common.Helpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -19,8 +22,9 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
private readonly IoTDBOptions _options;
|
private readonly IoTDBOptions _options;
|
||||||
private readonly TableSessionPool _sessionPool;
|
private readonly TableSessionPool _sessionPool;
|
||||||
private static readonly ConcurrentDictionary<Type, DeviceMetadata> _metadataCache = new();
|
private static readonly ConcurrentDictionary<Type, DeviceMetadata> _metadataCache = new();
|
||||||
|
private readonly ILogger<IoTDBProvider> _logger;
|
||||||
|
|
||||||
public IoTDBProvider(IOptions<IoTDBOptions> options)
|
public IoTDBProvider(IOptions<IoTDBOptions> options, ILogger<IoTDBProvider> logger)
|
||||||
{
|
{
|
||||||
_options = options.Value;
|
_options = options.Value;
|
||||||
|
|
||||||
@ -32,58 +36,20 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_sessionPool.Open(false).Wait();
|
_sessionPool.Open(false).Wait();
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取设备元数据
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
/// <returns></returns>
|
|
||||||
private DeviceMetadata GetMetadata<T>() where T : IoTEntity
|
|
||||||
{
|
|
||||||
return _metadataCache.GetOrAdd(typeof(T), type =>
|
|
||||||
{
|
|
||||||
var metadata = new DeviceMetadata();
|
|
||||||
foreach (var prop in type.GetProperties())
|
|
||||||
{
|
|
||||||
//标签列
|
|
||||||
var attrTAG = prop.GetCustomAttribute<TAGColumnAttribute>();
|
|
||||||
if (attrTAG != null)
|
|
||||||
{
|
|
||||||
metadata.ColumnCategories.Add(ColumnCategory.TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
//属性列
|
|
||||||
var attrATTRIBUTE = prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>();
|
|
||||||
if (attrATTRIBUTE != null)
|
|
||||||
{
|
|
||||||
metadata.ColumnCategories.Add(ColumnCategory.ATTRIBUTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//数据列
|
|
||||||
var attrFIELD = prop.GetCustomAttribute<FIELDColumnAttribute>();
|
|
||||||
if (attrFIELD != null)
|
|
||||||
{
|
|
||||||
metadata.ColumnCategories.Add(ColumnCategory.FIELD);
|
|
||||||
metadata.Measurements.Add(prop.Name);
|
|
||||||
metadata.DataTypes.Add(GetDataTypeFromStr(prop.PropertyType.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return metadata;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 插入数据
|
/// 插入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="entity"></param>
|
/// <param name="entity"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task InsertAsync<T>(T entity) where T : IoTEntity
|
public async Task InsertAsync<T>(T entity, int buildTabletMode) where T : IoTEntity
|
||||||
{
|
{
|
||||||
var metadata = GetMetadata<T>();
|
var metadata = GetMetadata<T>();
|
||||||
|
|
||||||
var tablet = BuildTablet(new[] { entity }, metadata);
|
var tablet = BuildTablet(new[] { entity }, metadata, buildTabletMode);
|
||||||
await _sessionPool.InsertAsync(tablet);
|
await _sessionPool.InsertAsync(tablet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,58 +59,46 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="entities"></param>
|
/// <param name="entities"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task BatchInsertAsync<T>(IEnumerable<T> entities) where T : IoTEntity
|
public async Task BatchInsertAsync<T>(IEnumerable<T> entities, int buildTabletMode) where T : IoTEntity
|
||||||
{
|
{
|
||||||
var metadata = GetMetadata<T>();
|
var metadata = GetMetadata<T>();
|
||||||
|
|
||||||
var batchSize = 1000;
|
var batchSize = 1000;
|
||||||
var batches = entities.Chunk(batchSize);
|
var batches = entities.Chunk(batchSize);
|
||||||
|
|
||||||
foreach (var batch in batches)
|
foreach (var batch in batches)
|
||||||
{
|
{
|
||||||
var tablet = BuildTablet(batch, metadata);
|
var tablet = BuildTablet(batch, metadata, buildTabletMode);
|
||||||
await _sessionPool.InsertAsync(tablet);
|
await _sessionPool.InsertAsync(tablet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构建表模型
|
/// 删除数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="entities"></param>
|
/// <param name="options"></param>
|
||||||
/// <param name="metadata"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata) where T : IoTEntity
|
public async Task<object> DeleteAsync<T>(QueryOptions options) where T : IoTEntity
|
||||||
{
|
{
|
||||||
var deviceId = DevicePathBuilder.GetDeviceId(entities.First());
|
var query = BuildDeleteSQL<T>(options);
|
||||||
var timestamps = new List<long>();
|
var sessionDataSet = await _sessionPool.ExecuteQueryStatementAsync(query);
|
||||||
var values = new List<List<object>>();
|
|
||||||
|
|
||||||
foreach (var entity in entities)
|
if (!sessionDataSet.HasNext())
|
||||||
{
|
{
|
||||||
timestamps.Add(entity.Timestamps);
|
_logger.LogWarning($"{typeof(T).Name} 删除数据时,没有返回受影响记录数量。");
|
||||||
var rowValues = new List<object>();
|
return 0;
|
||||||
foreach (var measurement in metadata.Measurements)
|
|
||||||
{
|
|
||||||
var value = typeof(T).GetProperty(measurement)?.GetValue(entity);
|
|
||||||
if(value == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,属性{measurement}值为空,不符合IoTDB设计标准,请赋值以后重新处理。");
|
|
||||||
}
|
|
||||||
rowValues.Add(value);
|
|
||||||
}
|
|
||||||
values.Add(rowValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tablet(
|
//获取唯一结果行
|
||||||
deviceId,
|
var row = sessionDataSet.Next();
|
||||||
metadata.Measurements,
|
return row.Values[0];
|
||||||
metadata.DataTypes,
|
|
||||||
values,
|
|
||||||
timestamps
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询数据
|
/// 查询数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -153,7 +107,7 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<PagedResult<T>> QueryAsync<T>(QueryOptions options) where T : IoTEntity, new()
|
public async Task<PagedResult<T>> QueryAsync<T>(QueryOptions options) where T : IoTEntity, new()
|
||||||
{
|
{
|
||||||
var query = BuildQuery<T>(options);
|
var query = BuildQuerySQL<T>(options);
|
||||||
var sessionDataSet = await _sessionPool.ExecuteQueryStatementAsync(query);
|
var sessionDataSet = await _sessionPool.ExecuteQueryStatementAsync(query);
|
||||||
|
|
||||||
var result = new PagedResult<T>
|
var result = new PagedResult<T>
|
||||||
@ -165,18 +119,75 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建表模型
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="entities">表实体</param>
|
||||||
|
/// <param name="metadata">设备元数据</param>
|
||||||
|
/// <param name="buildTabletMode">构建表模型方式,1 根据实体《T》直接显示指定Tag,2根据实体《T》的名称指定表名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata, int buildTabletMode) where T : IoTEntity
|
||||||
|
{
|
||||||
|
var timestamps = new List<long>();
|
||||||
|
var values = new List<List<object>>();
|
||||||
|
|
||||||
|
foreach (var entity in entities)
|
||||||
|
{
|
||||||
|
timestamps.Add(entity.Timestamps);
|
||||||
|
var rowValues = new List<object>();
|
||||||
|
foreach (var measurement in metadata.ColumnNames)
|
||||||
|
{
|
||||||
|
var value = typeof(T).GetProperty(measurement)?.GetValue(entity);
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,属性{measurement}值为空,不符合IoTDB设计标准,请赋值以后重新处理。");
|
||||||
|
}
|
||||||
|
rowValues.Add(value);
|
||||||
|
}
|
||||||
|
values.Add(rowValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildTabletMode == 1)
|
||||||
|
{
|
||||||
|
return new Tablet(
|
||||||
|
DevicePathBuilder.GetDeviceId(entities.First()),
|
||||||
|
metadata.ColumnNames,
|
||||||
|
metadata.ColumnCategories,
|
||||||
|
metadata.DataTypes,
|
||||||
|
values,
|
||||||
|
timestamps
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (buildTabletMode == 2)
|
||||||
|
{
|
||||||
|
return new Tablet(
|
||||||
|
DevicePathBuilder.GetTableName<T>(),
|
||||||
|
metadata.ColumnNames,
|
||||||
|
metadata.ColumnCategories,
|
||||||
|
metadata.DataTypes,
|
||||||
|
values,
|
||||||
|
timestamps
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,buildTabletMode参数值不正确,请赋值以后重新处理。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构建查询语句
|
/// 构建查询语句
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="options"></param>
|
/// <param name="options"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private string BuildQuery<T>(QueryOptions options) where T : IoTEntity
|
private string BuildQuerySQL<T>(QueryOptions options) where T : IoTEntity
|
||||||
{
|
{
|
||||||
var metadata = GetMetadata<T>();
|
var metadata = GetMetadata<T>();
|
||||||
var sb = new StringBuilder("SELECT ");
|
var sb = new StringBuilder("SELECT ");
|
||||||
sb.AppendJoin(", ", metadata.Measurements);
|
sb.AppendJoin(", ", metadata.ColumnNames);
|
||||||
sb.Append($" FROM {DevicePathBuilder.GetTableName<T>()}");
|
sb.Append($" FROM {options.TableNameOrTagName}");
|
||||||
|
|
||||||
if (options.Conditions.Any())
|
if (options.Conditions.Any())
|
||||||
{
|
{
|
||||||
@ -188,6 +199,30 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建删除语句
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string BuildDeleteSQL<T>(QueryOptions options) where T : IoTEntity
|
||||||
|
{
|
||||||
|
var metadata = GetMetadata<T>();
|
||||||
|
var sb = new StringBuilder("DELETE ");
|
||||||
|
|
||||||
|
sb.Append($" FROM {options.TableNameOrTagName}");
|
||||||
|
|
||||||
|
sb.AppendJoin(", ", metadata.ColumnNames);
|
||||||
|
|
||||||
|
if (options.Conditions.Any())
|
||||||
|
{
|
||||||
|
sb.Append(" WHERE ");
|
||||||
|
sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将查询条件转换为SQL语句
|
/// 将查询条件转换为SQL语句
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -213,7 +248,7 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<int> GetTotalCount<T>(QueryOptions options) where T : IoTEntity
|
private async Task<int> GetTotalCount<T>(QueryOptions options) where T : IoTEntity
|
||||||
{
|
{
|
||||||
var countQuery = $"SELECT COUNT(*) FROM {DevicePathBuilder.GetTableName<T>()}";
|
var countQuery = $"SELECT COUNT(*) FROM {options.TableNameOrTagName}";
|
||||||
if (options.Conditions.Any())
|
if (options.Conditions.Any())
|
||||||
{
|
{
|
||||||
countQuery += " WHERE " + string.Join(" AND ", options.Conditions.Select(TranslateCondition));
|
countQuery += " WHERE " + string.Join(" AND ", options.Conditions.Select(TranslateCondition));
|
||||||
@ -246,7 +281,7 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
foreach (var measurement in metadata.Measurements)
|
foreach (var measurement in metadata.ColumnNames)
|
||||||
{
|
{
|
||||||
var value = record.Values;
|
var value = record.Values;
|
||||||
|
|
||||||
@ -263,7 +298,7 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 释放资源
|
/// 释放资源
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -272,23 +307,196 @@ namespace JiShe.CollectBus.IoTDBProvider
|
|||||||
_sessionPool?.Close().Wait();
|
_sessionPool?.Close().Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TSDataType GetDataTypeFromStr(string str)
|
/// <summary>
|
||||||
|
/// 获取设备元数据
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
private DeviceMetadata GetMetadata<T>() where T : IoTEntity
|
||||||
{
|
{
|
||||||
return str switch
|
return _metadataCache.GetOrAdd(typeof(T), type =>
|
||||||
{
|
{
|
||||||
"BOOLEAN" => TSDataType.BOOLEAN,
|
var columns = CollectColumnMetadata(type);
|
||||||
"INT32" => TSDataType.INT32,
|
var metadata = BuildDeviceMetadata(columns);
|
||||||
"INT64" => TSDataType.INT64,
|
return metadata;
|
||||||
"FLOAT" => TSDataType.FLOAT,
|
});
|
||||||
"DOUBLE" => TSDataType.DOUBLE,
|
|
||||||
"TEXT" => TSDataType.TEXT,
|
//return _metadataCache.GetOrAdd(typeof(T), type =>
|
||||||
"NULLTYPE" => TSDataType.NONE,
|
//{
|
||||||
"TIMESTAMP" => TSDataType.TIMESTAMP,
|
// var metadata = new DeviceMetadata();
|
||||||
"DATE" => TSDataType.DATE,
|
// List<Tuple<string, ColumnCategory, TSDataType>> columns = new();
|
||||||
"BLOB" => TSDataType.BLOB,
|
// foreach (var prop in type.GetProperties())
|
||||||
"STRING" => TSDataType.STRING,
|
// {
|
||||||
_ => TSDataType.STRING
|
// //标签列
|
||||||
};
|
// var attrTAG = prop.GetCustomAttribute<TAGColumnAttribute>();
|
||||||
|
// if (attrTAG != null)
|
||||||
|
// {
|
||||||
|
// columns.Add(Tuple.Create(prop.PropertyType.Name, ColumnCategory.TAG, GetDataTypeFromStr(prop.PropertyType.Name)));
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //属性列
|
||||||
|
// var attrATTRIBUTE = prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>();
|
||||||
|
// if (attrATTRIBUTE != null)
|
||||||
|
// {
|
||||||
|
// columns.Add(Tuple.Create(prop.PropertyType.Name, ColumnCategory.ATTRIBUTE, GetDataTypeFromStr(prop.PropertyType.Name)));
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //数据列
|
||||||
|
// var attrFIELD = prop.GetCustomAttribute<FIELDColumnAttribute>();
|
||||||
|
// if (attrFIELD != null)
|
||||||
|
// {
|
||||||
|
// columns.Add(Tuple.Create(prop.PropertyType.Name, ColumnCategory.FIELD, GetDataTypeFromStr(prop.PropertyType.Name)));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// var columnCategories = EnumExtensions.ToEnumDictionary<ColumnCategory>();
|
||||||
|
// foreach (var item in columnCategories)
|
||||||
|
// {
|
||||||
|
// if (item.Value == ColumnCategory.TAG)
|
||||||
|
// {
|
||||||
|
// metadata.ColumnNames.AddRange(columns.Where(d => d.Item2 == ColumnCategory.FIELD).Select(d => d.Item1).ToList());
|
||||||
|
// metadata.ColumnCategories.AddRange(columns.Where(d => d.Item2 == ColumnCategory.TAG).Select(d => d.Item2).ToList());
|
||||||
|
// metadata.DataTypes.AddRange(columns.Where(d => d.Item2 == ColumnCategory.TAG).Select(d => d.Item3).ToList());
|
||||||
|
// }
|
||||||
|
// else if (item.Value == ColumnCategory.ATTRIBUTE)
|
||||||
|
// {
|
||||||
|
// metadata.ColumnNames.AddRange(columns.Where(d => d.Item2 == ColumnCategory.ATTRIBUTE).Select(d => d.Item1).ToList());
|
||||||
|
// metadata.ColumnCategories.AddRange(columns.Where(d => d.Item2 == ColumnCategory.ATTRIBUTE).Select(d => d.Item2).ToList());
|
||||||
|
// metadata.DataTypes.AddRange(columns.Where(d => d.Item2 == ColumnCategory.ATTRIBUTE).Select(d => d.Item3).ToList());
|
||||||
|
// }
|
||||||
|
// else if (item.Value == ColumnCategory.FIELD)
|
||||||
|
// {
|
||||||
|
// metadata.ColumnNames.AddRange(columns.Where(d => d.Item2 == ColumnCategory.FIELD).Select(d => d.Item1).ToList());
|
||||||
|
// metadata.ColumnCategories.AddRange(columns.Where(d => d.Item2 == ColumnCategory.FIELD).Select(d => d.Item2).ToList());
|
||||||
|
// metadata.DataTypes.AddRange(columns.Where(d => d.Item2 == ColumnCategory.FIELD).Select(d => d.Item3).ToList());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return metadata;
|
||||||
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取设备元数据的列
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private List<ColumnInfo> CollectColumnMetadata(Type type)
|
||||||
|
{
|
||||||
|
var columns = new List<ColumnInfo>();
|
||||||
|
|
||||||
|
foreach (var prop in type.GetProperties())
|
||||||
|
{
|
||||||
|
//按优先级顺序检查属性,避免重复反射
|
||||||
|
ColumnInfo? column = prop.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
|
name: prop.Name, //使用属性名
|
||||||
|
category: ColumnCategory.TAG,
|
||||||
|
dataType: GetDataTypeFromTypeName(prop.PropertyType.Name)
|
||||||
|
) : prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
|
prop.Name,
|
||||||
|
ColumnCategory.ATTRIBUTE,
|
||||||
|
GetDataTypeFromTypeName(prop.PropertyType.Name)
|
||||||
|
) : prop.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
|
prop.Name,
|
||||||
|
ColumnCategory.FIELD,
|
||||||
|
GetDataTypeFromTypeName(prop.PropertyType.Name)
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
if (column.HasValue)
|
||||||
|
{
|
||||||
|
columns.Add(column.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建设备元数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="columns"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private DeviceMetadata BuildDeviceMetadata(List<ColumnInfo> columns)
|
||||||
|
{
|
||||||
|
var metadata = new DeviceMetadata();
|
||||||
|
|
||||||
|
//按业务逻辑顺序处理(TAG -> FIELD -> ATTRIBUTE)
|
||||||
|
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);
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理不同列类型的逻辑
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="groupedColumns"></param>
|
||||||
|
/// <param name="category"></param>
|
||||||
|
/// <param name="metadata"></param>
|
||||||
|
private void ProcessCategory(IReadOnlyDictionary<ColumnCategory, List<ColumnInfo>> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据列结构
|
||||||
|
/// </summary>
|
||||||
|
private readonly struct ColumnInfo
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public ColumnCategory Category { get; }
|
||||||
|
public TSDataType DataType { get; }
|
||||||
|
|
||||||
|
public ColumnInfo(string name, ColumnCategory category, TSDataType dataType)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Category = category;
|
||||||
|
DataType = dataType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据类型名称获取对应的 IoTDB 数据类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="typeName">类型名称(不区分大小写)</param>
|
||||||
|
/// <returns>对应的 TSDataType,默认返回 TSDataType.STRING</returns>
|
||||||
|
private TSDataType GetDataTypeFromTypeName(string typeName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(typeName))
|
||||||
|
return TSDataType.STRING;
|
||||||
|
|
||||||
|
return DataTypeMap.TryGetValue(typeName.Trim(), out var dataType)
|
||||||
|
? dataType
|
||||||
|
: TSDataType.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据类型名称获取 IoTDB 数据类型
|
||||||
|
/// </summary>
|
||||||
|
private readonly IReadOnlyDictionary<string, TSDataType> DataTypeMap =
|
||||||
|
new Dictionary<string, TSDataType>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["BOOLEAN"] = TSDataType.BOOLEAN,
|
||||||
|
["INT32"] = TSDataType.INT32,
|
||||||
|
["INT64"] = TSDataType.INT64,
|
||||||
|
["FLOAT"] = TSDataType.FLOAT,
|
||||||
|
["DOUBLE"] = TSDataType.DOUBLE,
|
||||||
|
["TEXT"] = TSDataType.TEXT,
|
||||||
|
["NULLTYPE"] = TSDataType.NONE,
|
||||||
|
["TIMESTAMP"] = TSDataType.TIMESTAMP,
|
||||||
|
["DATE"] = TSDataType.DATE,
|
||||||
|
["BLOB"] = TSDataType.BLOB,
|
||||||
|
["STRING"] = TSDataType.STRING
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user