From fa6fad0a570467b99218f36ea7149699542a22a4 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Thu, 23 Apr 2026 18:39:05 +0200 Subject: [PATCH] Aggiunto modello e migrations x MtcSetup --- MP.Core/Objects/MachDataItem.cs | 25 ++++ MP.Data/DataServiceCollectionExtensions.cs | 44 ++++++ MP.Data/DbModels/Mtc/MtcSetupModel.cs | 24 ++++ ...0260423153623_AddMtcSetupModel.Designer.cs | 127 ++++++++++++++++++ .../20260423153623_AddMtcSetupModel.cs | 30 +++++ .../MoonPro_UtilsContextModelSnapshot.cs | 13 ++ MP.Data/MoonProContext.cs | 33 +++-- MP.Data/MoonPro_UtilsContext.cs | 2 + MP.Data/Repository/Mtc/IMtcSetupRepository.cs | 13 ++ MP.Data/Repository/Mtc/MtcSetupRepository.cs | 58 ++++++++ MP.Data/Services/Mtc/IMtcSetupService.cs | 23 ++++ MP.Data/Services/Mtc/MtcSetupService.cs | 60 +++++++++ 12 files changed, 435 insertions(+), 17 deletions(-) create mode 100644 MP.Core/Objects/MachDataItem.cs create mode 100644 MP.Data/DataServiceCollectionExtensions.cs create mode 100644 MP.Data/DbModels/Mtc/MtcSetupModel.cs create mode 100644 MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs create mode 100644 MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs create mode 100644 MP.Data/Repository/Mtc/IMtcSetupRepository.cs create mode 100644 MP.Data/Repository/Mtc/MtcSetupRepository.cs create mode 100644 MP.Data/Services/Mtc/IMtcSetupService.cs create mode 100644 MP.Data/Services/Mtc/MtcSetupService.cs diff --git a/MP.Core/Objects/MachDataItem.cs b/MP.Core/Objects/MachDataItem.cs new file mode 100644 index 00000000..32bf1e56 --- /dev/null +++ b/MP.Core/Objects/MachDataItem.cs @@ -0,0 +1,25 @@ +namespace MP.Core.Objects +{ + public class MachDataItem + { + public enum DataItemCategory + { + CONDITION = 0, + EVENT = 1, + SAMPLE = 2 + } + + public string Uuid { get; set; } = ""; + + public DataItemCategory Category { get; set; } + + public string Name { get; set; } = ""; + + public string SubType { get; set; } = ""; + + public string Type { get; set; } = ""; + + public string Units { get; set; } = ""; + + } +} diff --git a/MP.Data/DataServiceCollectionExtensions.cs b/MP.Data/DataServiceCollectionExtensions.cs new file mode 100644 index 00000000..a37ac980 --- /dev/null +++ b/MP.Data/DataServiceCollectionExtensions.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using MP.Data.Repository.Mtc; +using MP.Data.Repository.Utils; +using MP.Data.Services.Mtc; +using MP.Data.Services.Utils; + +namespace MP.Data +{ + public static class DataServiceCollectionExtensions + { + public static IServiceCollection AddIocSetup(this IServiceCollection services) + { + //// DbContextFactory: preferibile in Blazor Server e scenari concorrenti + //services.AddDbContextFactory(options => + // options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); + + //// servizi preliminari + ////services.TryAddSingleton(redisConn); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + + // Repository Scoped + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + + // Servizi Scoped + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + + //// aggiunta servizi finali Singleton... + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + + + return services; + } + } +} diff --git a/MP.Data/DbModels/Mtc/MtcSetupModel.cs b/MP.Data/DbModels/Mtc/MtcSetupModel.cs new file mode 100644 index 00000000..a6faef44 --- /dev/null +++ b/MP.Data/DbModels/Mtc/MtcSetupModel.cs @@ -0,0 +1,24 @@ +using MP.Core.Objects; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json; + +namespace MP.Data.DbModels.Mtc +{ + [Table("mtc_setup")] + public class MtcSetupModel + { + [Key] + public string IdxMacchina { get; set; } + + public string MtcDataItemsRaw { get; set; } = ""; + + [NotMapped] + public List MtcDataItems + { + get => string.IsNullOrWhiteSpace(MtcDataItemsRaw) ? new List() : JsonSerializer.Deserialize>(MtcDataItemsRaw) ?? new(); + set => MtcDataItemsRaw = JsonSerializer.Serialize(value); + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs new file mode 100644 index 00000000..d8ac5a54 --- /dev/null +++ b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs @@ -0,0 +1,127 @@ +// +using System; +using MP.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MP.Data.Migrations.MoonPro_Utils +{ + [DbContext(typeof(MoonPro_UtilsContext))] + [Migration("20260423153623_AddMtcSetupModel")] + partial class AddMtcSetupModel + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("SQL_Latin1_General_CP1_CI_AS") + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("MP.Data.DbModels.Mtc.MtcSetupModel", b => + { + b.Property("IdxMacchina") + .HasColumnType("nvarchar(450)"); + + b.Property("MtcDataItemsRaw") + .HasColumnType("nvarchar(max)"); + + b.HasKey("IdxMacchina"); + + b.ToTable("mtc_setup"); + }); + + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("AvgDuration") + .HasColumnType("float"); + + b.Property("Destination") + .HasColumnType("nvarchar(450)"); + + b.Property("Hour") + .HasColumnType("datetime2"); + + b.Property("MachineId") + .HasColumnType("nvarchar(450)"); + + b.Property("MaxDuration") + .HasColumnType("float"); + + b.Property("MinDuration") + .HasColumnType("float"); + + b.Property("NoReply") + .HasColumnType("bigint"); + + b.Property("RequestCount") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Destination", "MachineId", "Hour") + .IsUnique() + .HasDatabaseName("idx_statsaggr_env_mach_hour") + .HasFilter("[Destination] IS NOT NULL AND [MachineId] IS NOT NULL"); + + b.ToTable("stats_aggr"); + }); + + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsDetailModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("AvgDuration") + .HasColumnType("float"); + + b.Property("Destination") + .HasColumnType("nvarchar(450)"); + + b.Property("Hour") + .HasColumnType("datetime2"); + + b.Property("MaxDuration") + .HasColumnType("float"); + + b.Property("MinDuration") + .HasColumnType("float"); + + b.Property("NoReply") + .HasColumnType("bigint"); + + b.Property("RequestCount") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Destination", "Type", "Hour") + .IsUnique() + .HasDatabaseName("idx_statsdet_hour_env_type") + .HasFilter("[Destination] IS NOT NULL AND [Type] IS NOT NULL"); + + b.ToTable("stats_detail"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs new file mode 100644 index 00000000..5873df04 --- /dev/null +++ b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MP.Data.Migrations.MoonPro_Utils +{ + public partial class AddMtcSetupModel : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "mtc_setup", + columns: table => new + { + IdxMacchina = table.Column(type: "nvarchar(450)", nullable: false), + MtcDataItemsRaw = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_mtc_setup", x => x.IdxMacchina); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "mtc_setup"); + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs index f935fcb6..531fb160 100644 --- a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs +++ b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs @@ -23,6 +23,19 @@ namespace MP.Data.Migrations.MoonPro_Utils SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("MP.Data.DbModels.Mtc.MtcSetupModel", b => + { + b.Property("IdxMacchina") + .HasColumnType("nvarchar(450)"); + + b.Property("MtcDataItemsRaw") + .HasColumnType("nvarchar(max)"); + + b.HasKey("IdxMacchina"); + + b.ToTable("mtc_setup"); + }); + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b => { b.Property("Id") diff --git a/MP.Data/MoonProContext.cs b/MP.Data/MoonProContext.cs index 975aaedd..70fb8f40 100644 --- a/MP.Data/MoonProContext.cs +++ b/MP.Data/MoonProContext.cs @@ -108,7 +108,6 @@ namespace MP.Data public virtual DbSet DbSetTksScore { get; set; } public virtual DbSet DbSetRemRebLog { get; set; } - #endregion Public Properties #region Private Methods @@ -151,27 +150,27 @@ namespace MP.Data modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS"); modelBuilder.Entity(entity => - { - entity.HasKey(e => e.CodArticolo); + { + entity.HasKey(e => e.CodArticolo); - entity.ToView("v_UI_AnagArticoli"); + entity.ToView("v_UI_AnagArticoli"); - entity.Property(e => e.CodArticolo) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.CodArticolo) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.DescArticolo) - .IsRequired() - .HasMaxLength(250); + entity.Property(e => e.DescArticolo) + .IsRequired() + .HasMaxLength(250); - entity.Property(e => e.Disegno) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.Disegno) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.Tipo) - .IsRequired() - .HasMaxLength(50); - }); + entity.Property(e => e.Tipo) + .IsRequired() + .HasMaxLength(50); + }); modelBuilder.Entity(entity => { entity.HasKey(e => e.CodArticolo); diff --git a/MP.Data/MoonPro_UtilsContext.cs b/MP.Data/MoonPro_UtilsContext.cs index bbcc6ac7..2875ed97 100644 --- a/MP.Data/MoonPro_UtilsContext.cs +++ b/MP.Data/MoonPro_UtilsContext.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using MP.Data.DbModels.Mtc; using MP.Data.DbModels.Utils; using NLog; using System; @@ -47,6 +48,7 @@ namespace MP.Data public virtual DbSet DbSetStatsDet { get; set; } public virtual DbSet DbSetStatsAggr { get; set; } + public virtual DbSet DbSetMtcSetup { get; set; } #endregion Public Properties diff --git a/MP.Data/Repository/Mtc/IMtcSetupRepository.cs b/MP.Data/Repository/Mtc/IMtcSetupRepository.cs new file mode 100644 index 00000000..0ad39b52 --- /dev/null +++ b/MP.Data/Repository/Mtc/IMtcSetupRepository.cs @@ -0,0 +1,13 @@ +using MP.Data.DbModels.Mtc; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Mtc +{ + public interface IMtcSetupRepository + { + Task GetByIdxAsync(string idxMacchina); + Task InsertAsync(MtcSetupModel newRec); + Task DeleteAsync(string idxMacchina); + Task UpdateAsync(MtcSetupModel updRec); + } +} diff --git a/MP.Data/Repository/Mtc/MtcSetupRepository.cs b/MP.Data/Repository/Mtc/MtcSetupRepository.cs new file mode 100644 index 00000000..1a52b9d5 --- /dev/null +++ b/MP.Data/Repository/Mtc/MtcSetupRepository.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels.Mtc; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Mtc +{ + public class MtcSetupRepository : BaseRepository, IMtcSetupRepository + { + #region Public Constructors + + public MtcSetupRepository(IDbContextFactory ctxFactory) : base(ctxFactory) + { + } + + #endregion Public Constructors + + #region Public Methods + + /// + public async Task DeleteAsync(string idxMacchina) + { + await using var dbCtx = await CreateContextAsync(); + var existing = await GetByIdxAsync(idxMacchina); + if (existing != null) + { + dbCtx.DbSetMtcSetup.Remove(existing); + await dbCtx.SaveChangesAsync(); + } + } + + /// + public async Task GetByIdxAsync(string idxMacchina) + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetMtcSetup + .Include(s => s.MtcDataItems) + .FirstOrDefaultAsync(s => s.IdxMacchina == idxMacchina); + } + + /// + public async Task InsertAsync(MtcSetupModel newRec) + { + await using var dbCtx = await CreateContextAsync(); + dbCtx.DbSetMtcSetup.Add(newRec); + await dbCtx.SaveChangesAsync(); + } + + /// + public async Task UpdateAsync(MtcSetupModel updRec) + { + await using var dbCtx = await CreateContextAsync(); + dbCtx.DbSetMtcSetup.Update(updRec); + await dbCtx.SaveChangesAsync(); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/MP.Data/Services/Mtc/IMtcSetupService.cs b/MP.Data/Services/Mtc/IMtcSetupService.cs new file mode 100644 index 00000000..010597d1 --- /dev/null +++ b/MP.Data/Services/Mtc/IMtcSetupService.cs @@ -0,0 +1,23 @@ +using MP.Core.Objects; +using MP.Data.DbModels.Mtc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Services.Mtc +{ + public interface IMtcSetupService + { + + /// + /// Replace the data set for the specified machine. + /// Deletes existing record then inserts new one. + /// + Task ReplaceMachineDataAsync(string idxMacchina, List items); + + + /// + /// Retrieve all data for a given machine. + /// + Task GetMachineDataAsync(string idxMacchina); + } +} diff --git a/MP.Data/Services/Mtc/MtcSetupService.cs b/MP.Data/Services/Mtc/MtcSetupService.cs new file mode 100644 index 00000000..7604ff37 --- /dev/null +++ b/MP.Data/Services/Mtc/MtcSetupService.cs @@ -0,0 +1,60 @@ +using Microsoft.Extensions.Configuration; +using MP.Core.Objects; +using MP.Data.DbModels.Mtc; +using MP.Data.Repository.Mtc; +using StackExchange.Redis; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Services.Mtc +{ + // A lightweight service that mirrors the old Mongo based archive + public class MtcSetupService : BaseServ, IMtcSetupService + { + + private readonly string _className; + private readonly IMtcSetupRepository _repo; + + public MtcSetupService( + IConfiguration config, + IConnectionMultiplexer redis, + IMtcSetupRepository repo) : base(config, redis) + { + _className = "MtcSetup"; + _repo = repo; + } + + /// + public async Task ReplaceMachineDataAsync(string idxMacchina, List items) + { + return await TraceAsync($"{_className}.ReplaceMachineData", async (activity) => + { + string operation = "Upsert"; + await _repo.DeleteAsync(idxMacchina); + activity?.SetTag("db.operation", operation); + var setup = new MtcSetupModel + { + IdxMacchina = idxMacchina, + MtcDataItems = items + }; + await _repo.InsertAsync(setup); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + return true; + }); + } + + /// + public async Task GetMachineDataAsync(string idxMacchina) + { + return await TraceAsync($"{_className}.GetMachineData", async (activity) => + { + string cacheKey = $"{_redisBaseKey}:{_className}:MachData:{idxMacchina}"; + return await GetOrSetCacheAsync( + cacheKey, + async () => await _repo.GetByIdxAsync(idxMacchina), + LongCache + ); + }); + } + } +}