From acf562fc0a52e07bde907873ff400bca10667908 Mon Sep 17 00:00:00 2001 From: Hocine Hacherouf Date: Sun, 11 Sep 2022 17:05:45 +0200 Subject: [PATCH] Add migration of device tags from st table to database #1209 --- ...1150200_Add DeviceModelCommand.Designer.cs | 86 +++++++++++++++++++ .../20220911150200_Add DeviceModelCommand.cs | 37 ++++++++ .../PortalDbContextModelSnapshot.cs | 27 ++++++ .../PortalDbContext.cs | 1 + .../Seeds/DeviceModelCommandSeeder.cs | 46 ++++++++++ src/AzureIoTHub.Portal/Server/Startup.cs | 3 + .../Entities/DeviceModelCommand.cs | 23 +++++ 7 files changed, 223 insertions(+) create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.Designer.cs create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.cs create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs create mode 100644 src/AzureIoTHubPortal.Domain/Entities/DeviceModelCommand.cs diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.Designer.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.Designer.cs new file mode 100644 index 000000000..5ca71cec6 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.Designer.cs @@ -0,0 +1,86 @@ +// +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.Infrastructure.Migrations +{ + [DbContext(typeof(PortalDbContext))] + [Migration("20220911150200_Add DeviceModelCommand")] + partial class AddDeviceModelCommand + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Confirmed") + .HasColumnType("boolean"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Frame") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelCommands"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsWritable") + .HasColumnType("boolean"); + + b.Property("ModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PropertyType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelProperties"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.cs new file mode 100644 index 000000000..9ffe3abd0 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/20220911150200_Add DeviceModelCommand.cs @@ -0,0 +1,37 @@ +// 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.Infrastructure.Migrations +{ + using Microsoft.EntityFrameworkCore.Migrations; + + public partial class AddDeviceModelCommand : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + _ = migrationBuilder.CreateTable( + name: "DeviceModelCommands", + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + Frame = table.Column(type: "text", nullable: false), + Confirmed = table.Column(type: "boolean", nullable: false), + Port = table.Column(type: "integer", nullable: false), + IsBuiltin = table.Column(type: "boolean", nullable: false), + DeviceModelId = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + _ = table.PrimaryKey("PK_DeviceModelCommands", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + _ = migrationBuilder.DropTable( + name: "DeviceModelCommands"); + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs b/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs index 5bfa19394..f60a60b7a 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs @@ -21,6 +21,33 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Confirmed") + .HasColumnType("boolean"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Frame") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelCommands"); + }); + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b => { b.Property("Id") diff --git a/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs b/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs index 34378ff04..f649b631d 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs @@ -13,6 +13,7 @@ namespace AzureIoTHub.Portal.Infrastructure public class PortalDbContext : DbContext { public DbSet DeviceModelProperties { get; set; } + public DbSet DeviceModelCommands { get; set; } #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public PortalDbContext(DbContextOptions options) diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs new file mode 100644 index 000000000..bb4769a43 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs @@ -0,0 +1,46 @@ +// 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.Seeds +{ + using System.Globalization; + using Azure.Data.Tables; + using Domain; + using Domain.Entities; + using Factories; + using Microsoft.EntityFrameworkCore; + + internal static class DeviceModelCommandSeeder + { + public static async Task MigrateDeviceModelCommands(this PortalDbContext ctx, ConfigHandler config) + { + var table = new TableClientFactory(config.StorageAccountConnectionString) + .GetDeviceCommands(); + + var set = ctx.Set(); + + foreach (var item in table.Query().ToArray()) + { + if (await set.AnyAsync(c => c.Id == item.RowKey)) + continue; + +#pragma warning disable CS8629 // Nullable value type may be null. + _ = await set.AddAsync(new DeviceModelCommand + { + Id = item.RowKey, + Frame = item[nameof(DeviceModelCommand.Frame)].ToString(), + Port = int.Parse(item[nameof(DeviceModelCommand.Port)].ToString(), CultureInfo.InvariantCulture), + IsBuiltin = bool.Parse(item[nameof(DeviceModelCommand.IsBuiltin)]?.ToString() ?? "false"), + Confirmed = bool.Parse(item[nameof(DeviceModelCommand.Confirmed)]?.ToString() ?? "false"), + DeviceModelId = item.PartitionKey + }); +#pragma warning restore CS8629 // Nullable value type may be null. + + if (config is ProductionConfigHandler) + { + _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); + } + } + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Startup.cs b/src/AzureIoTHub.Portal/Server/Startup.cs index 851f70ba8..7a9b26cad 100644 --- a/src/AzureIoTHub.Portal/Server/Startup.cs +++ b/src/AzureIoTHub.Portal/Server/Startup.cs @@ -445,6 +445,9 @@ private static async Task EnsureDatabaseCreatedAndUpToDate(IApplicationBuilder a await context .MigrateDeviceModelProperties(config); + await context + .MigrateDeviceModelCommands(config); + _ = await context.SaveChangesAsync(); } catch (InvalidOperationException e) diff --git a/src/AzureIoTHubPortal.Domain/Entities/DeviceModelCommand.cs b/src/AzureIoTHubPortal.Domain/Entities/DeviceModelCommand.cs new file mode 100644 index 000000000..1dc5ec16b --- /dev/null +++ b/src/AzureIoTHubPortal.Domain/Entities/DeviceModelCommand.cs @@ -0,0 +1,23 @@ +// 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.Entities +{ + using Base; + using System.ComponentModel.DataAnnotations.Schema; + + public class DeviceModelCommand : EntityBase + { + [NotMapped] public string Name => Id; + + public string Frame { get; set; } + + public bool Confirmed { get; set; } + + public int Port { get; set; } = 1; + + public bool IsBuiltin { get; set; } + + public string DeviceModelId { get; set; } + } +}