From eb10f23c89d15385a976a0a8e3d503aa94a111f2 Mon Sep 17 00:00:00 2001 From: pengxiwei Date: Tue, 24 May 2022 18:09:06 +0800 Subject: [PATCH 1/2] =?UTF-8?q?pengxiwei:=E5=B0=81=E8=A3=85Taos=E5=BA=93?= =?UTF-8?q?=E7=9A=84ORM=EF=BC=8C=E6=8C=81=E7=BB=AD=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EFCore.Taos.sln | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/EFCore.Taos.sln b/EFCore.Taos.sln index 7ea0fa5..425eb51 100644 --- a/EFCore.Taos.sln +++ b/EFCore.Taos.sln @@ -26,7 +26,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.HealthChecks.Taos" EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{1F3895A2-ED79-499F-A6A1-3F88A3D8D7F7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCore.Taos.Tests", "src\EntityFrameworkCore.Taos.Tests\EntityFrameworkCore.Taos.Tests.csproj", "{7F5F12D6-CA82-4499-AF3E-6CA7E61579CB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Taos.Tests", "src\EntityFrameworkCore.Taos.Tests\EntityFrameworkCore.Taos.Tests.csproj", "{7F5F12D6-CA82-4499-AF3E-6CA7E61579CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaosOrm", "..\TaosOrm\TaosOrm.csproj", "{7F9F4104-3AFF-4D1E-8AD4-154957159ADC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -110,6 +112,18 @@ Global {7F5F12D6-CA82-4499-AF3E-6CA7E61579CB}.Release|x64.Build.0 = Release|Any CPU {7F5F12D6-CA82-4499-AF3E-6CA7E61579CB}.Release|x86.ActiveCfg = Release|Any CPU {7F5F12D6-CA82-4499-AF3E-6CA7E61579CB}.Release|x86.Build.0 = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|x64.ActiveCfg = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|x64.Build.0 = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|x86.ActiveCfg = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Debug|x86.Build.0 = Debug|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|Any CPU.Build.0 = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|x64.ActiveCfg = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|x64.Build.0 = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|x86.ActiveCfg = Release|Any CPU + {7F9F4104-3AFF-4D1E-8AD4-154957159ADC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- Gitee From 1b90cd201a33aa52125416ab2e085a5efdb5c640 Mon Sep 17 00:00:00 2001 From: pengxiwei Date: Wed, 25 May 2022 09:07:47 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=20=E5=B0=81=E8=A3=85Taos=E5=BA=93=E7=9A=84?= =?UTF-8?q?ORM=EF=BC=8C=E6=8C=81=E7=BB=AD=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TaosOrm/Program.cs | 23 +++++ TaosOrm/TaosAttribute.cs | 55 ++++++++++ TaosOrm/TaosDataType.cs | 26 +++++ TaosOrm/TaosOrm.csproj | 12 +++ TaosOrm/TaosSugar.cs | 204 +++++++++++++++++++++++++++++++++++++ TaosOrm/Test/EntityDemo.cs | 32 ++++++ 6 files changed, 352 insertions(+) create mode 100644 TaosOrm/Program.cs create mode 100644 TaosOrm/TaosAttribute.cs create mode 100644 TaosOrm/TaosDataType.cs create mode 100644 TaosOrm/TaosOrm.csproj create mode 100644 TaosOrm/TaosSugar.cs create mode 100644 TaosOrm/Test/EntityDemo.cs diff --git a/TaosOrm/Program.cs b/TaosOrm/Program.cs new file mode 100644 index 0000000..c9a9a0f --- /dev/null +++ b/TaosOrm/Program.cs @@ -0,0 +1,23 @@ +using System; +using TaosOrm.Test; + +namespace TaosOrm +{ + internal class Program + { + static void Main(string[] args) + { + TaosSugar taosSugar = new TaosSugar(); + taosSugar.TaosAddAsync( + new EntityDemo() + { + Current = 2, + Phase = 30, + Voltage = 4, + EquipId = "3afbe36dd5b740a6b7c1634b70687d51", + GroupId = 1 + }, true); + Console.WriteLine("Hello World!"); + } + } +} diff --git a/TaosOrm/TaosAttribute.cs b/TaosOrm/TaosAttribute.cs new file mode 100644 index 0000000..7a88390 --- /dev/null +++ b/TaosOrm/TaosAttribute.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaosOrm +{ + [Serializable] + public class TaosAttribute : Attribute + { + + /// + /// 超级表 + /// + public string SuperTableName { get; } + /// + /// 构造函数 + /// + /// 超级表名 + public TaosAttribute(string superTableName) + { + SuperTableName = superTableName; + } + } + [Serializable] + public class TaosColumnAttribute : Attribute + { + /// + /// 列名字 + /// + public string ColumnName { get; set; } + /// + /// 列类型 + /// + public TaosDataType ColumnType { get; set; } + public string ColumnLength { get; set; } + /// + /// 是否标签 + /// + public bool IsTag { get; set; } = false; + /// + /// 是否为表名 + /// + public bool IsTableName { get; set; } + public TaosColumnAttribute(string columnName, TaosDataType columnType, string columnLength = null, bool isTag = false, bool isTableName = false) + { + ColumnName = columnName; + ColumnType = columnType; + ColumnLength = columnLength; + IsTag = isTag; + IsTableName = isTableName; + } + } +} diff --git a/TaosOrm/TaosDataType.cs b/TaosOrm/TaosDataType.cs new file mode 100644 index 0000000..659b507 --- /dev/null +++ b/TaosOrm/TaosDataType.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaosOrm +{ + /// + /// 涛思时序数据库10种数据类型 + /// https://www.bookstack.cn/read/TDengin-2.0-zh/spilt.1.33f53af4c5509954.md + /// + public enum TaosDataType + { + TIMESTAMP, + INT, + BIGINT, + FLOAT, + DOUBLE, + BINARY, + SMALLINT, + TINYINT, + BOOL, + NCHAR + } +} diff --git a/TaosOrm/TaosOrm.csproj b/TaosOrm/TaosOrm.csproj new file mode 100644 index 0000000..a5c3b75 --- /dev/null +++ b/TaosOrm/TaosOrm.csproj @@ -0,0 +1,12 @@ + + + + Exe + net5.0 + + + + + + + diff --git a/TaosOrm/TaosSugar.cs b/TaosOrm/TaosSugar.cs new file mode 100644 index 0000000..ea004da --- /dev/null +++ b/TaosOrm/TaosSugar.cs @@ -0,0 +1,204 @@ +using IoTSharp.Data.Taos; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace TaosOrm +{ + /// + /// 时序数据库Orm 查询未实现 + /// + public class TaosSugar + { + private readonly TaosConnection _taos; + private static readonly ConcurrentDictionary _tableStructure = new();// 表名缓存 + public TaosSugar() + { + _taos = new TaosConnection("连接地址"); + if (_taos.State != System.Data.ConnectionState.Open) _taos.Open(); + } + /// + /// 数据新增 + /// + /// 实体对象 + /// + /// 为True 检查超级表结构是否存在不存在就创建 + /// + public async Task TaosAddAsync(TEntity entity, bool checkDB = false) where TEntity : class + { + //获取超级表结构 + var st = GetSuperTaosStructure(entity); + //获取值列表 + StringBuilder tagValue = new StringBuilder(); + StringBuilder columnValue = new StringBuilder(); + PropertyInfo[] infos = entity.GetType().GetProperties(); + if (checkDB) CheckDataBase(st, infos);//监测表结构是否存在 + TaosColumnAttribute dfAttr = null; + object[] dfAttrs; + int tags = 0; + int columns = 0; + foreach (PropertyInfo info in infos) + { + dfAttrs = info.GetCustomAttributes(typeof(TaosColumnAttribute), false); + if (dfAttrs.Length > 0) + { + dfAttr = dfAttrs[0] as TaosColumnAttribute; + if (dfAttr is TaosColumnAttribute) + { + if (dfAttr.IsTag) + { + if (dfAttr.IsTableName)//是不是为表名的字段 + { + st.TableName = info.GetValue(entity, null).ToString(); + } + //tagName.Append(tags > 0 ? "," + dfAttr.ColumnName : dfAttr.ColumnName); + if (dfAttr.ColumnType == TaosDataType.BINARY || dfAttr.ColumnType == TaosDataType.NCHAR)//字符串就得加'' + { + tagValue.Append(tags > 0 ? "," + $"'{info.GetValue(entity, null)}'" : $"'{info.GetValue(entity, null)}'"); + } + else + { + tagValue.Append(tags > 0 ? "," + info.GetValue(entity, null) : info.GetValue(entity, null)); + } + tags++; + } + else + { + //columnName.Append(columns > 0 ? "," + dfAttr.ColumnName : dfAttr.ColumnName); + if (dfAttr.ColumnType == TaosDataType.BINARY || dfAttr.ColumnType == TaosDataType.NCHAR)//字符串就得加'' + { + columnValue.Append(columns > 0 ? "," + $"'{info.GetValue(entity, null)}'" : $"'{info.GetValue(entity, null)}'"); + } + else + { + columnValue.Append(columns > 0 ? "," + info.GetValue(entity, null) : info.GetValue(entity, null)); + } + columns++; + } + } + } + } + if (st.TableName == null) throw new Exception("未设备表名特性"); + string strInsertSQL = @$"INSERT INTO D_{st.TableName} USING + {st.SuperTableName} + ({string.Join(",", st.TagNames)}) TAGS({tagValue}) + (ts,{string.Join(",", st.ColumnNames)}) VALUES(now,{columnValue})"; +#if DEBUG + Console.WriteLine($"TaosSql:{strInsertSQL}"); +#endif + return await _taos.CreateCommand(strInsertSQL).ExecuteNonQueryAsync(); + } + /// + /// 缓存超级表结构 + /// + /// + /// + /// + /// + private static TaosStructure GetSuperTaosStructure(TEntity entity) where TEntity : class + { + Type entityType = entity.GetType(); + PropertyInfo[] infos = entityType.GetProperties(); + TaosStructure dt = _tableStructure.ContainsKey(entityType.FullName) ? _tableStructure[entityType.FullName] : null; + if (dt == null) + { + TaosStructure taos = new TaosStructure(); + TaosColumnAttribute dfAttr = null; + object[] dfAttrs; + if (entityType.GetCustomAttributes(typeof(TaosAttribute), false)[0] is TaosAttribute dtAttr) + { + taos.SuperTableName = dtAttr.SuperTableName; + } + else + { + throw new Exception(entityType.ToString() + "未设置DataTable特性。"); + } + foreach (PropertyInfo info in infos) + { + dfAttrs = info.GetCustomAttributes(typeof(TaosColumnAttribute), false); + if (dfAttrs.Length > 0) + { + dfAttr = dfAttrs[0] as TaosColumnAttribute; + if (dfAttr is TaosColumnAttribute) + { + if (dfAttr.IsTag) + { + taos.TagNames.Add(dfAttr.ColumnName); + } + else + { + taos.ColumnNames.Add(dfAttr.ColumnName); + } + } + } + } + _tableStructure[entityType.FullName] = taos; + return taos; + } + return dt; + } + /// + /// 创建DB与超级表 + /// + /// + /// + private void CheckDataBase(TaosStructure st, PropertyInfo[] infos) + { + //backlog:切换DB不能实现 有BUG + _taos.CreateCommand($"CREATE DATABASE IF NOT EXISTS {_taos.Database} KEEP 365 DAYS 10 BLOCKS 4;").ExecuteNonQuery(); + _taos.ChangeDatabase(_taos.Database);//创建后切换DB + StringBuilder columnTag = new StringBuilder(); + StringBuilder column = new StringBuilder(); + TaosColumnAttribute dfAttr = null; + object[] dfAttrs; + int tags = 0; + int columns = 0; + foreach (PropertyInfo info in infos) + { + dfAttrs = info.GetCustomAttributes(typeof(TaosColumnAttribute), false); + if (dfAttrs.Length > 0) + { + dfAttr = dfAttrs[0] as TaosColumnAttribute; + if (dfAttr is TaosColumnAttribute) + { + string length = ""; + if (dfAttr.ColumnLength != null) + { + length = $"({dfAttr.ColumnLength})";//判断数据类型是否有长度有些没有长度 + } + if (dfAttr.IsTag)//是标签 + { + string tag = $"{dfAttr.ColumnName} {dfAttr.ColumnType}{length}"; + columnTag.Append(tags > 0 ? "," + tag : tag); + tags++; + } + else + { + string tag = $"{dfAttr.ColumnName} {dfAttr.ColumnType}{length}"; + column.Append(columns > 0 ? "," + tag : tag); + columns++; + } + } + } + } + //创建超级表 + _taos.CreateCommand($@"CREATE TABLE IF NOT EXISTS {_taos.Database}.{st.SuperTableName} + (`ts` TIMESTAMP, + {column}) TAGS ({columnTag});") + .ExecuteNonQuery(); + } + + + } + public class TaosStructure + { + public string TableName { get; set; }//表名是动态值 (为设备ID) + public string SuperTableName { get; set; } + public List TagNames { get; set; } = new List(); + public List ColumnNames { get; set; } = new List(); + } +} diff --git a/TaosOrm/Test/EntityDemo.cs b/TaosOrm/Test/EntityDemo.cs new file mode 100644 index 0000000..8c9eef6 --- /dev/null +++ b/TaosOrm/Test/EntityDemo.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TaosOrm.Test +{ + [Taos("BREAKER_BASIC")]//超级表名 + [Description("时序表")] + public class EntityDemo + { + /// + /// 特性含义:别名,类型,类型长度,是否为Tag,是否为表名[表名只能设置一个字段] + /// + [TaosColumn("equipId", TaosDataType.BINARY, "64", true, true)] + public string EquipId { get; set; } + + [TaosColumn("groupid", TaosDataType.INT, isTag: true)] + public int GroupId { get; set; } + + [TaosColumn("current", TaosDataType.FLOAT)] + public double Current { get; set; } + + [TaosColumn("voltage", TaosDataType.INT)] + public int Voltage { get; set; } + + [TaosColumn("phase", TaosDataType.FLOAT)] + public double Phase { get; set; } + } +} -- Gitee