diff --git a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs
index dfbe9248f..d66ca86c8 100644
--- a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs
+++ b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs
@@ -70,5 +70,9 @@ public abstract class ConfigHandler
public abstract string IdeasAuthenticationToken { get; }
public abstract string PostgreSQLConnectionString { get; }
+
+ public abstract string MySQLConnectionString { get; }
+
+ public abstract string DbProvider { get; }
}
}
diff --git a/src/AzureIoTHub.Portal.Domain/Shared/Constants/DbProviders.cs b/src/AzureIoTHub.Portal.Domain/Shared/Constants/DbProviders.cs
new file mode 100644
index 000000000..e18364170
--- /dev/null
+++ b/src/AzureIoTHub.Portal.Domain/Shared/Constants/DbProviders.cs
@@ -0,0 +1,13 @@
+// Copyright (c) CGI France. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace AzureIoTHub.Portal.Domain.Shared.Constants
+{
+
+ public static class DbProviders
+ {
+ public const string PostgreSQL = "PostgreSQL";
+
+ public const string MySQL = "MySQL";
+ }
+}
diff --git a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj
index cd9bfad5f..adc46d7b3 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj
+++ b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj
@@ -134,6 +134,7 @@
+
diff --git a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs
index bf3fdaefc..0b3fc80bf 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs
+++ b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs
@@ -16,6 +16,8 @@ internal abstract class ConfigHandlerBase : ConfigHandler
internal const string DPSIDScopeKey = "IoTDPS:IDScope";
internal const string UseSecurityHeadersKey = "UseSecurityHeaders";
internal const string PostgreSQLConnectionStringKey = "PostgreSQL:ConnectionString";
+ internal const string MySQLConnectionStringKey = "MySQL:ConnectionString";
+ internal const string DbProviderKey = "DbProvider";
internal const string OIDCScopeKey = "OIDC:Scope";
internal const string OIDCAuthorityKey = "OIDC:Authority";
diff --git a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs
index e3e89ddb4..b2b80b6c1 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs
+++ b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs
@@ -3,6 +3,7 @@
namespace AzureIoTHub.Portal.Infrastructure
{
+ using AzureIoTHub.Portal.Domain.Shared.Constants;
using Microsoft.Extensions.Configuration;
internal class DevelopmentConfigHandler : ConfigHandlerBase
@@ -76,5 +77,9 @@ internal DevelopmentConfigHandler(IConfiguration config)
public override string IdeasAuthenticationToken => this.config.GetValue(IdeasAuthenticationTokenKey, string.Empty);
public override string PostgreSQLConnectionString => this.config[PostgreSQLConnectionStringKey];
+
+ public override string MySQLConnectionString => this.config[MySQLConnectionStringKey];
+
+ public override string DbProvider => this.config.GetValue(DbProviderKey, DbProviders.PostgreSQL);
}
}
diff --git a/src/AzureIoTHub.Portal.Infrastructure/Helpers/DatabaseHelper.cs b/src/AzureIoTHub.Portal.Infrastructure/Helpers/DatabaseHelper.cs
new file mode 100644
index 000000000..1904b856b
--- /dev/null
+++ b/src/AzureIoTHub.Portal.Infrastructure/Helpers/DatabaseHelper.cs
@@ -0,0 +1,24 @@
+// Copyright (c) CGI France. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace AzureIoTHub.Portal.Infrastructure.Helpers
+{
+ using System;
+ using Microsoft.EntityFrameworkCore;
+
+ public static class DatabaseHelper
+ {
+ public static ServerVersion GetMySqlServerVersion(string mySQLConnectionString)
+ {
+ try
+ {
+ return ServerVersion.AutoDetect(mySQLConnectionString);
+ }
+ catch (ArgumentException ex)
+ {
+ Console.WriteLine(ex.Message);
+ return new MySqlServerVersion(new Version(8, 0, 32));
+ }
+ }
+ }
+}
diff --git a/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs
index 5eb85a7de..15f21963a 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs
+++ b/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs
@@ -3,6 +3,7 @@
namespace AzureIoTHub.Portal.Infrastructure
{
+ using AzureIoTHub.Portal.Domain.Shared.Constants;
using Microsoft.Extensions.Configuration;
internal class ProductionConfigHandler : ConfigHandlerBase
@@ -38,6 +39,10 @@ internal ProductionConfigHandler(IConfiguration config)
public override string PostgreSQLConnectionString => this.config.GetConnectionString(PostgreSQLConnectionStringKey);
+ public override string MySQLConnectionString => this.config.GetConnectionString(MySQLConnectionStringKey);
+
+ public override string DbProvider => this.config.GetValue(DbProviderKey, DbProviders.PostgreSQL);
+
public override int StorageAccountDeviceModelImageMaxAge => this.config.GetValue(StorageAccountDeviceModelImageMaxAgeKey, 86400);
public override bool UseSecurityHeaders => this.config.GetValue(UseSecurityHeadersKey, true);
diff --git a/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs b/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs
index ee4e2dbdf..e25c42ead 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs
+++ b/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs
@@ -14,7 +14,9 @@ namespace AzureIoTHub.Portal.Infrastructure.Startup
using AzureIoTHub.Portal.Domain;
using AzureIoTHub.Portal.Domain.Options;
using AzureIoTHub.Portal.Domain.Repositories;
+ using AzureIoTHub.Portal.Domain.Shared.Constants;
using AzureIoTHub.Portal.Infrastructure.Extensions;
+ using AzureIoTHub.Portal.Infrastructure.Helpers;
using AzureIoTHub.Portal.Infrastructure.Jobs;
using AzureIoTHub.Portal.Infrastructure.Managers;
using AzureIoTHub.Portal.Infrastructure.Mappers;
@@ -102,23 +104,45 @@ private static IServiceCollection ConfigureDeviceRegstryDependencies(this IServi
private static IServiceCollection ConfigureDatabase(this IServiceCollection services, ConfigHandler configuration)
{
- _ = services
- .AddDbContextPool(opts =>
- {
- _ = opts.UseNpgsql(configuration.PostgreSQLConnectionString);
- _ = opts.UseExceptionProcessor();
- });
+ var dbContextOptions = new DbContextOptionsBuilder();
- if (string.IsNullOrEmpty(configuration.PostgreSQLConnectionString))
- return services;
+ switch (configuration.DbProvider)
+ {
+ case DbProviders.PostgreSQL:
+ if (string.IsNullOrEmpty(configuration.PostgreSQLConnectionString))
+ {
+ return services;
+ }
+ _ = services.AddDbContextPool(opts =>
+ {
+ _ = opts.UseNpgsql(configuration.PostgreSQLConnectionString, x => x.MigrationsAssembly("AzureIoTHub.Portal.Postgres"));
+ _ = opts.UseExceptionProcessor();
+ });
+ _ = dbContextOptions.UseNpgsql(configuration.PostgreSQLConnectionString, x => x.MigrationsAssembly("AzureIoTHub.Portal.Postgres"));
+ break;
+ case DbProviders.MySQL:
+ if (string.IsNullOrEmpty(configuration.MySQLConnectionString))
+ {
+ return services;
+ }
+ _ = services.AddDbContextPool(opts =>
+ {
+ _ = opts.UseMySql(configuration.MySQLConnectionString, DatabaseHelper.GetMySqlServerVersion(configuration.MySQLConnectionString), x => x.MigrationsAssembly("AzureIoTHub.Portal.MySql"));
+ _ = opts.UseExceptionProcessor();
+ });
+ _ = dbContextOptions.UseMySql(configuration.MySQLConnectionString, DatabaseHelper.GetMySqlServerVersion(configuration.MySQLConnectionString), x => x.MigrationsAssembly("AzureIoTHub.Portal.MySql"));
+ break;
+ default:
+ return services;
+ }
_ = services.AddScoped>();
- var dbContextOptions = new DbContextOptionsBuilder();
- _ = dbContextOptions.UseNpgsql(configuration.PostgreSQLConnectionString);
-
- using var ctx = new PortalDbContext(dbContextOptions.Options);
- ctx.Database.Migrate();
+ using var portalDbContext = new PortalDbContext(dbContextOptions.Options);
+ if (portalDbContext.Database.CanConnect())
+ {
+ portalDbContext.Database.Migrate();
+ }
return services;
}
diff --git a/src/AzureIoTHub.Portal.MySql/AzureIoTHub.Portal.MySql.csproj b/src/AzureIoTHub.Portal.MySql/AzureIoTHub.Portal.MySql.csproj
new file mode 100644
index 000000000..bcf5eaf31
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/AzureIoTHub.Portal.MySql.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.Designer.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.Designer.cs
similarity index 91%
rename from src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.Designer.cs
rename to src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.Designer.cs
index e25e391f5..3441adee9 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.Designer.cs
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.Designer.cs
@@ -1,4 +1,4 @@
-//
+//
using AzureIoTHub.Portal.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -8,7 +8,7 @@
#nullable disable
-namespace AzureIoTHub.Portal.Infrastructure.Migrations
+namespace AzureIoTHub.Portal.MySql.Migrations
{
[DbContext(typeof(PortalDbContext))]
[Migration("20220903171411_Initial Create")]
diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.cs
similarity index 89%
rename from src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.cs
rename to src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.cs
index 578f8d336..a4833ed7d 100644
--- a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220903171411_Initial Create.cs
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20220903171411_Initial Create.cs
@@ -3,7 +3,7 @@
#nullable disable
-namespace AzureIoTHub.Portal.Infrastructure.Migrations
+namespace AzureIoTHub.Portal.MySql.Migrations
{
using Microsoft.EntityFrameworkCore.Migrations;
diff --git a/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.Designer.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.Designer.cs
new file mode 100644
index 000000000..bb6d836cd
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.Designer.cs
@@ -0,0 +1,24 @@
+//
+using AzureIoTHub.Portal.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace AzureIoTHub.Portal.MySql.Migrations
+{
+ [DbContext(typeof(PortalDbContext))]
+ [Migration("20220910143007_Add Quartz .NET tables")]
+ partial class AddQuartzNETtables
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.cs
new file mode 100644
index 000000000..778ee3949
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20220910143007_Add Quartz .NET tables.cs
@@ -0,0 +1,22 @@
+// Copyright (c) CGI France. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#nullable disable
+
+namespace AzureIoTHub.Portal.MySql.Migrations
+{
+ using Microsoft.EntityFrameworkCore.Migrations;
+
+ public partial class AddQuartzNETtables : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ _ = migrationBuilder.Sql("DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;\r\nDROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;\r\nDROP TABLE IF EXISTS QRTZ_LOCKS;\r\nDROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_JOB_DETAILS;\r\nDROP TABLE IF EXISTS QRTZ_CALENDARS;\r\n\r\n\r\nCREATE TABLE QRTZ_JOB_DETAILS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n\tJOB_NAME VARCHAR(200) NOT NULL,\r\n JOB_GROUP VARCHAR(200) NOT NULL,\r\n DESCRIPTION VARCHAR(250) NULL,\r\n JOB_CLASS_NAME VARCHAR(250) NOT NULL, \r\n IS_DURABLE BOOLEAN NOT NULL,\r\n IS_NONCONCURRENT BOOLEAN NOT NULL,\r\n IS_UPDATE_DATA BOOLEAN NOT NULL,\r\n\tREQUESTS_RECOVERY BOOLEAN NOT NULL,\r\n JOB_DATA BLOB NULL,\r\n PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_TRIGGERS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n\tTRIGGER_NAME VARCHAR(200) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL,\r\n JOB_NAME VARCHAR(200) NOT NULL, \r\n JOB_GROUP VARCHAR(200) NOT NULL,\r\n DESCRIPTION VARCHAR(250) NULL,\r\n NEXT_FIRE_TIME BIGINT(13) NULL,\r\n PREV_FIRE_TIME BIGINT(13) NULL,\r\n PRIORITY INTEGER NULL,\r\n TRIGGER_STATE VARCHAR(16) NOT NULL,\r\n TRIGGER_TYPE VARCHAR(8) NOT NULL,\r\n START_TIME BIGINT(13) NOT NULL,\r\n END_TIME BIGINT(13) NULL,\r\n CALENDAR_NAME VARCHAR(200) NULL,\r\n MISFIRE_INSTR SMALLINT(2) NULL,\r\n JOB_DATA BLOB NULL,\r\n PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) \r\n\t\tREFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) \r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_SIMPLE_TRIGGERS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n\tTRIGGER_NAME VARCHAR(200) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL,\r\n REPEAT_COUNT BIGINT(7) NOT NULL,\r\n REPEAT_INTERVAL BIGINT(12) NOT NULL,\r\n TIMES_TRIGGERED BIGINT(10) NOT NULL,\r\n PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) \r\n\t\tREFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_SIMPROP_TRIGGERS \r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n TRIGGER_NAME VARCHAR(200) NOT NULL ,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL ,\r\n STR_PROP_1 VARCHAR(512) NULL,\r\n STR_PROP_2 VARCHAR(512) NULL,\r\n STR_PROP_3 VARCHAR(512) NULL,\r\n INT_PROP_1 INT NULL,\r\n INT_PROP_2 INT NULL,\r\n LONG_PROP_1 BIGINT NULL,\r\n LONG_PROP_2 BIGINT NULL,\r\n DEC_PROP_1 NUMERIC(13,4) NULL,\r\n DEC_PROP_2 NUMERIC(13,4) NULL,\r\n BOOL_PROP_1 BOOLEAN NULL,\r\n BOOL_PROP_2 BOOLEAN NULL,\r\n TIME_ZONE_ID VARCHAR(80) NULL,\r\n\tPRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) \r\n\t\tREFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_CRON_TRIGGERS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n TRIGGER_NAME VARCHAR(200) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL,\r\n CRON_EXPRESSION VARCHAR(120) NOT NULL,\r\n TIME_ZONE_ID VARCHAR(80),\r\n PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) \r\n\t\tREFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_BLOB_TRIGGERS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n TRIGGER_NAME VARCHAR(200) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL,\r\n BLOB_DATA BLOB NULL,\r\n PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n INDEX (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),\r\n FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) \r\n\t\tREFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_CALENDARS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n CALENDAR_NAME VARCHAR(200) NOT NULL, \r\n CALENDAR BLOB NOT NULL,\r\n PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL, \r\n PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_FIRED_TRIGGERS \r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n ENTRY_ID VARCHAR(95) NOT NULL,\r\n TRIGGER_NAME VARCHAR(200) NOT NULL,\r\n TRIGGER_GROUP VARCHAR(200) NOT NULL,\r\n INSTANCE_NAME VARCHAR(200) NOT NULL,\r\n FIRED_TIME BIGINT(13) NOT NULL,\r\n\tSCHED_TIME BIGINT(13) NOT NULL,\r\n PRIORITY INTEGER NOT NULL,\r\n STATE VARCHAR(16) NOT NULL,\r\n JOB_NAME VARCHAR(200) NULL,\r\n JOB_GROUP VARCHAR(200) NULL,\r\n IS_NONCONCURRENT BOOLEAN NOT NULL,\r\n REQUESTS_RECOVERY BOOLEAN NULL,\r\n PRIMARY KEY (SCHED_NAME,ENTRY_ID)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_SCHEDULER_STATE \r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n INSTANCE_NAME VARCHAR(200) NOT NULL,\r\n LAST_CHECKIN_TIME BIGINT(13) NOT NULL,\r\n CHECKIN_INTERVAL BIGINT(13) NOT NULL,\r\n PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE TABLE QRTZ_LOCKS\r\n (\r\n SCHED_NAME VARCHAR(120) NOT NULL,\r\n LOCK_NAME VARCHAR(40) NOT NULL, \r\n PRIMARY KEY (SCHED_NAME,LOCK_NAME)\r\n)ENGINE=InnoDB;\r\n\r\nCREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);\r\nCREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);\r\nCREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);\r\nCREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);\r\nCREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);\r\nCREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);\r\nCREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);\r\nCREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);\r\nCREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);\r\nCREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);\r\nCREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);\r\nCREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);\r\nCREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);\r\nCREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);\r\nCREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);\r\nCREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);\r\nCREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);\r\nCREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);\r\nCREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);\r\nCREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);\r\n");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ _ = migrationBuilder.Sql("DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;\r\nDROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;\r\nDROP TABLE IF EXISTS QRTZ_LOCKS;\r\nDROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_TRIGGERS;\r\nDROP TABLE IF EXISTS QRTZ_JOB_DETAILS;\r\nDROP TABLE IF EXISTS QRTZ_CALENDARS;\r\n");
+ }
+ }
+}
diff --git a/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.Designer.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.Designer.cs
new file mode 100644
index 000000000..54fdfb063
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.Designer.cs
@@ -0,0 +1,584 @@
+//
+using System;
+using AzureIoTHub.Portal.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace AzureIoTHub.Portal.MySql.Migrations
+{
+ [DbContext(typeof(PortalDbContext))]
+ [Migration("20230127211555_InitDatabase")]
+ partial class InitDatabase
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Concentrator", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ClientThumbprint")
+ .HasColumnType("longtext");
+
+ b.Property("DeviceType")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IsConnected")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LoraRegion")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("Concentrators");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DeviceModelId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("IsConnected")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("StatusUpdatedTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceModelId");
+
+ b.ToTable("Devices", (string)null);
+
+ b.UseTptMappingStrategy();
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ABPRelaxMode")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AppEUI")
+ .HasColumnType("longtext");
+
+ b.Property("ClassType")
+ .HasColumnType("int");
+
+ b.Property("Deduplication")
+ .HasColumnType("int");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Downlink")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsBuiltin")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("KeepAliveTimeout")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("PreferredWindow")
+ .HasColumnType("int");
+
+ b.Property("RXDelay")
+ .HasColumnType("int");
+
+ b.Property("SensorDecoder")
+ .HasColumnType("longtext");
+
+ b.Property("SupportLoRaFeatures")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseOTAA")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceModels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Confirmed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("DeviceModelId")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Frame")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IsBuiltin")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Port")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceModelCommands");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IsWritable")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ModelId")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Order")
+ .HasColumnType("int");
+
+ b.Property("PropertyType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceModelProperties");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTag", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Label")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Required")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Searchable")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceTags");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DeviceId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("EdgeDeviceId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceId");
+
+ b.HasIndex("EdgeDeviceId");
+
+ b.ToTable("DeviceTagValues");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ConnectionState")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("DeviceModelId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("NbDevices")
+ .HasColumnType("int");
+
+ b.Property("NbModules")
+ .HasColumnType("int");
+
+ b.Property("Scope")
+ .HasColumnType("longtext");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceModelId");
+
+ b.ToTable("EdgeDevices");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("EdgeDeviceModels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModelCommand", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("EdgeDeviceModelId")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ModuleName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("EdgeDeviceModelCommands");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Color")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("DeviceId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DeviceModelId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("EdgeDeviceId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("EdgeDeviceModelId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceId");
+
+ b.HasIndex("DeviceModelId");
+
+ b.HasIndex("EdgeDeviceId");
+
+ b.HasIndex("EdgeDeviceModelId");
+
+ b.ToTable("Labels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("EnqueuedTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LorawanDeviceId")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Telemetry")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LorawanDeviceId");
+
+ b.ToTable("LoRaDeviceTelemetry");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b =>
+ {
+ b.HasBaseType("AzureIoTHub.Portal.Domain.Entities.Device");
+
+ b.Property("ABPRelaxMode")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AlreadyLoggedInOnce")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AppEUI")
+ .HasColumnType("longtext");
+
+ b.Property("AppKey")
+ .HasColumnType("longtext");
+
+ b.Property("AppSKey")
+ .HasColumnType("longtext");
+
+ b.Property("ClassType")
+ .HasColumnType("int");
+
+ b.Property("DataRate")
+ .HasColumnType("longtext");
+
+ b.Property("Deduplication")
+ .HasColumnType("int");
+
+ b.Property("DevAddr")
+ .HasColumnType("longtext");
+
+ b.Property("Downlink")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("FCntDownStart")
+ .HasColumnType("int");
+
+ b.Property("FCntResetCounter")
+ .HasColumnType("int");
+
+ b.Property("FCntUpStart")
+ .HasColumnType("int");
+
+ b.Property("GatewayID")
+ .HasColumnType("longtext");
+
+ b.Property("KeepAliveTimeout")
+ .HasColumnType("int");
+
+ b.Property("NbRep")
+ .HasColumnType("longtext");
+
+ b.Property("NwkSKey")
+ .HasColumnType("longtext");
+
+ b.Property("PreferredWindow")
+ .HasColumnType("int");
+
+ b.Property("RX1DROffset")
+ .HasColumnType("int");
+
+ b.Property("RX2DataRate")
+ .HasColumnType("int");
+
+ b.Property("RXDelay")
+ .HasColumnType("int");
+
+ b.Property("ReportedRX1DROffset")
+ .HasColumnType("longtext");
+
+ b.Property("ReportedRX2DataRate")
+ .HasColumnType("longtext");
+
+ b.Property("ReportedRXDelay")
+ .HasColumnType("longtext");
+
+ b.Property("SensorDecoder")
+ .HasColumnType("longtext");
+
+ b.Property("Supports32BitFCnt")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("TxPower")
+ .HasColumnType("longtext");
+
+ b.Property("UseOTAA")
+ .HasColumnType("tinyint(1)");
+
+ b.ToTable("LorawanDevices", (string)null);
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", "DeviceModel")
+ .WithMany()
+ .HasForeignKey("DeviceModelId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DeviceModel");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null)
+ .WithMany("Tags")
+ .HasForeignKey("DeviceId");
+
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null)
+ .WithMany("Tags")
+ .HasForeignKey("EdgeDeviceId");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", "DeviceModel")
+ .WithMany()
+ .HasForeignKey("DeviceModelId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DeviceModel");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null)
+ .WithMany("Labels")
+ .HasForeignKey("DeviceId");
+
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", null)
+ .WithMany("Labels")
+ .HasForeignKey("DeviceModelId");
+
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null)
+ .WithMany("Labels")
+ .HasForeignKey("EdgeDeviceId");
+
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", null)
+ .WithMany("Labels")
+ .HasForeignKey("EdgeDeviceModelId");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", null)
+ .WithMany("Telemetry")
+ .HasForeignKey("LorawanDeviceId");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b =>
+ {
+ b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null)
+ .WithOne()
+ .HasForeignKey("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b =>
+ {
+ b.Navigation("Labels");
+
+ b.Navigation("Tags");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b =>
+ {
+ b.Navigation("Labels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b =>
+ {
+ b.Navigation("Labels");
+
+ b.Navigation("Tags");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b =>
+ {
+ b.Navigation("Labels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b =>
+ {
+ b.Navigation("Telemetry");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.cs b/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.cs
new file mode 100644
index 000000000..b739f8dfd
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/20230127211555_InitDatabase.cs
@@ -0,0 +1,478 @@
+// Copyright (c) CGI France. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#nullable disable
+
+namespace AzureIoTHub.Portal.MySql.Migrations
+{
+ using System;
+ using Microsoft.EntityFrameworkCore.Migrations;
+
+ ///
+ public partial class InitDatabase : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ _ = migrationBuilder.AlterDatabase()
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "Concentrators",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ LoraRegion = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceType = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ ClientThumbprint = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ IsConnected = table.Column(type: "tinyint(1)", nullable: false),
+ IsEnabled = table.Column(type: "tinyint(1)", nullable: false),
+ Version = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_Concentrators", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "DeviceModelCommands",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Frame = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Confirmed = table.Column(type: "tinyint(1)", nullable: false),
+ Port = table.Column(type: "int", nullable: false),
+ IsBuiltin = table.Column(type: "tinyint(1)", nullable: false),
+ DeviceModelId = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_DeviceModelCommands", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "DeviceModelProperties",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DisplayName = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ IsWritable = table.Column(type: "tinyint(1)", nullable: false),
+ Order = table.Column(type: "int", nullable: false),
+ PropertyType = table.Column(type: "int", nullable: false),
+ ModelId = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_DeviceModelProperties", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "DeviceModels",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Description = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ IsBuiltin = table.Column(type: "tinyint(1)", nullable: false),
+ SupportLoRaFeatures = table.Column(type: "tinyint(1)", nullable: false),
+ UseOTAA = table.Column(type: "tinyint(1)", nullable: true),
+ PreferredWindow = table.Column(type: "int", nullable: true),
+ Deduplication = table.Column(type: "int", nullable: true),
+ ClassType = table.Column(type: "int", nullable: false),
+ ABPRelaxMode = table.Column(type: "tinyint(1)", nullable: true),
+ Downlink = table.Column(type: "tinyint(1)", nullable: true),
+ KeepAliveTimeout = table.Column(type: "int", nullable: true),
+ RXDelay = table.Column(type: "int", nullable: true),
+ SensorDecoder = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ AppEUI = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_DeviceModels", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "DeviceTags",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Label = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Required = table.Column(type: "tinyint(1)", nullable: false),
+ Searchable = table.Column(type: "tinyint(1)", nullable: false)
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_DeviceTags", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "EdgeDeviceModelCommands",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ EdgeDeviceModelId = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ ModuleName = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_EdgeDeviceModelCommands", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "EdgeDeviceModels",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Description = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_EdgeDeviceModels", x => x.Id);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "Devices",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceModelId = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ IsConnected = table.Column(type: "tinyint(1)", nullable: false),
+ IsEnabled = table.Column(type: "tinyint(1)", nullable: false),
+ StatusUpdatedTime = table.Column(type: "datetime(6)", nullable: false),
+ Version = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_Devices", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_Devices_DeviceModels_DeviceModelId",
+ column: x => x.DeviceModelId,
+ principalTable: "DeviceModels",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "EdgeDevices",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceModelId = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Version = table.Column(type: "int", nullable: false),
+ ConnectionState = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ IsEnabled = table.Column(type: "tinyint(1)", nullable: false),
+ Scope = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ NbDevices = table.Column(type: "int", nullable: false),
+ NbModules = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_EdgeDevices", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_EdgeDevices_EdgeDeviceModels_DeviceModelId",
+ column: x => x.DeviceModelId,
+ principalTable: "EdgeDeviceModels",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "LorawanDevices",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ UseOTAA = table.Column(type: "tinyint(1)", nullable: false),
+ AppKey = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ AppEUI = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ AppSKey = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ NwkSKey = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DevAddr = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ AlreadyLoggedInOnce = table.Column(type: "tinyint(1)", nullable: false),
+ DataRate = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ TxPower = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ NbRep = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ ReportedRX2DataRate = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ ReportedRX1DROffset = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ ReportedRXDelay = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ GatewayID = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Downlink = table.Column(type: "tinyint(1)", nullable: true),
+ ClassType = table.Column(type: "int", nullable: false),
+ PreferredWindow = table.Column(type: "int", nullable: false),
+ Deduplication = table.Column(type: "int", nullable: false),
+ RX1DROffset = table.Column(type: "int", nullable: true),
+ RX2DataRate = table.Column(type: "int", nullable: true),
+ RXDelay = table.Column(type: "int", nullable: true),
+ ABPRelaxMode = table.Column(type: "tinyint(1)", nullable: true),
+ FCntUpStart = table.Column(type: "int", nullable: true),
+ FCntDownStart = table.Column(type: "int", nullable: true),
+ FCntResetCounter = table.Column(type: "int", nullable: true),
+ Supports32BitFCnt = table.Column(type: "tinyint(1)", nullable: true),
+ KeepAliveTimeout = table.Column(type: "int", nullable: true),
+ SensorDecoder = table.Column(type: "longtext", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_LorawanDevices", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_LorawanDevices_Devices_Id",
+ column: x => x.Id,
+ principalTable: "Devices",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "DeviceTagValues",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Value = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ EdgeDeviceId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_DeviceTagValues", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_DeviceTagValues_Devices_DeviceId",
+ column: x => x.DeviceId,
+ principalTable: "Devices",
+ principalColumn: "Id");
+ _ = table.ForeignKey(
+ name: "FK_DeviceTagValues_EdgeDevices_EdgeDeviceId",
+ column: x => x.EdgeDeviceId,
+ principalTable: "EdgeDevices",
+ principalColumn: "Id");
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "Labels",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Name = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ Color = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ DeviceModelId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ EdgeDeviceId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ EdgeDeviceModelId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_Labels", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_Labels_DeviceModels_DeviceModelId",
+ column: x => x.DeviceModelId,
+ principalTable: "DeviceModels",
+ principalColumn: "Id");
+ _ = table.ForeignKey(
+ name: "FK_Labels_Devices_DeviceId",
+ column: x => x.DeviceId,
+ principalTable: "Devices",
+ principalColumn: "Id");
+ _ = table.ForeignKey(
+ name: "FK_Labels_EdgeDeviceModels_EdgeDeviceModelId",
+ column: x => x.EdgeDeviceModelId,
+ principalTable: "EdgeDeviceModels",
+ principalColumn: "Id");
+ _ = table.ForeignKey(
+ name: "FK_Labels_EdgeDevices_EdgeDeviceId",
+ column: x => x.EdgeDeviceId,
+ principalTable: "EdgeDevices",
+ principalColumn: "Id");
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateTable(
+ name: "LoRaDeviceTelemetry",
+ columns: table => new
+ {
+ Id = table.Column(type: "varchar(255)", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ EnqueuedTime = table.Column(type: "datetime(6)", nullable: false),
+ Telemetry = table.Column(type: "longtext", nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4"),
+ LorawanDeviceId = table.Column(type: "varchar(255)", nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4")
+ },
+ constraints: table =>
+ {
+ _ = table.PrimaryKey("PK_LoRaDeviceTelemetry", x => x.Id);
+ _ = table.ForeignKey(
+ name: "FK_LoRaDeviceTelemetry_LorawanDevices_LorawanDeviceId",
+ column: x => x.LorawanDeviceId,
+ principalTable: "LorawanDevices",
+ principalColumn: "Id");
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_Devices_DeviceModelId",
+ table: "Devices",
+ column: "DeviceModelId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_DeviceTagValues_DeviceId",
+ table: "DeviceTagValues",
+ column: "DeviceId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_DeviceTagValues_EdgeDeviceId",
+ table: "DeviceTagValues",
+ column: "EdgeDeviceId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_EdgeDevices_DeviceModelId",
+ table: "EdgeDevices",
+ column: "DeviceModelId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_Labels_DeviceId",
+ table: "Labels",
+ column: "DeviceId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_Labels_DeviceModelId",
+ table: "Labels",
+ column: "DeviceModelId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_Labels_EdgeDeviceId",
+ table: "Labels",
+ column: "EdgeDeviceId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_Labels_EdgeDeviceModelId",
+ table: "Labels",
+ column: "EdgeDeviceModelId");
+
+ _ = migrationBuilder.CreateIndex(
+ name: "IX_LoRaDeviceTelemetry_LorawanDeviceId",
+ table: "LoRaDeviceTelemetry",
+ column: "LorawanDeviceId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ _ = migrationBuilder.DropTable(
+ name: "Concentrators");
+
+ _ = migrationBuilder.DropTable(
+ name: "DeviceModelCommands");
+
+ _ = migrationBuilder.DropTable(
+ name: "DeviceModelProperties");
+
+ _ = migrationBuilder.DropTable(
+ name: "DeviceTags");
+
+ _ = migrationBuilder.DropTable(
+ name: "DeviceTagValues");
+
+ _ = migrationBuilder.DropTable(
+ name: "EdgeDeviceModelCommands");
+
+ _ = migrationBuilder.DropTable(
+ name: "Labels");
+
+ _ = migrationBuilder.DropTable(
+ name: "LoRaDeviceTelemetry");
+
+ _ = migrationBuilder.DropTable(
+ name: "EdgeDevices");
+
+ _ = migrationBuilder.DropTable(
+ name: "LorawanDevices");
+
+ _ = migrationBuilder.DropTable(
+ name: "EdgeDeviceModels");
+
+ _ = migrationBuilder.DropTable(
+ name: "Devices");
+
+ _ = migrationBuilder.DropTable(
+ name: "DeviceModels");
+ }
+ }
+}
diff --git a/src/AzureIoTHub.Portal.MySql/Migrations/PortalDbContextModelSnapshot.cs b/src/AzureIoTHub.Portal.MySql/Migrations/PortalDbContextModelSnapshot.cs
new file mode 100644
index 000000000..dc3f31c7a
--- /dev/null
+++ b/src/AzureIoTHub.Portal.MySql/Migrations/PortalDbContextModelSnapshot.cs
@@ -0,0 +1,581 @@
+//
+using System;
+using AzureIoTHub.Portal.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace AzureIoTHub.Portal.MySql.Migrations
+{
+ [DbContext(typeof(PortalDbContext))]
+ partial class PortalDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Concentrator", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ClientThumbprint")
+ .HasColumnType("longtext");
+
+ b.Property("DeviceType")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IsConnected")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LoraRegion")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("Concentrators");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DeviceModelId")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("IsConnected")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("StatusUpdatedTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceModelId");
+
+ b.ToTable("Devices", (string)null);
+
+ b.UseTptMappingStrategy();
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ABPRelaxMode")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AppEUI")
+ .HasColumnType("longtext");
+
+ b.Property("ClassType")
+ .HasColumnType("int");
+
+ b.Property("Deduplication")
+ .HasColumnType("int");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Downlink")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsBuiltin")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("KeepAliveTimeout")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("PreferredWindow")
+ .HasColumnType("int");
+
+ b.Property("RXDelay")
+ .HasColumnType("int");
+
+ b.Property("SensorDecoder")
+ .HasColumnType("longtext");
+
+ b.Property("SupportLoRaFeatures")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseOTAA")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceModels");
+ });
+
+ modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("varchar(255)");
+
+ b.Property