Aggiunto modello e migrations x MtcSetup

This commit is contained in:
Samuele Locatelli
2026-04-23 18:39:05 +02:00
parent dd13704423
commit fa6fad0a57
12 changed files with 435 additions and 17 deletions
+25
View File
@@ -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; } = "";
}
}
@@ -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<DataLayerContext>(options =>
// options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
//// servizi preliminari
////services.TryAddSingleton<IConnectionMultiplexer>(redisConn);
//services.TryAddSingleton<IRedisService, RedisService>();
//services.TryAddSingleton<IRedisSubscriptionManager, RedisSubscriptionManager>();
// Repository Scoped
services.TryAddScoped<IMtcSetupRepository, MtcSetupRepository>();
services.TryAddScoped<IStatsAggrRepository, StatsAggrRepository>();
services.TryAddScoped<IStatsDetailRepository, StatsDetailRepository>();
// Servizi Scoped
services.TryAddScoped<IMtcSetupService, MtcSetupService>();
services.TryAddScoped<IStatsAggrService, StatsAggrService>();
services.TryAddScoped<IStatsDetailService, StatsDetailService>();
//// aggiunta servizi finali Singleton...
//services.TryAddSingleton<IImageCacheService, ImageCacheService>();
//services.TryAddSingleton<IConfigDataService, ConfigDataService>();
//services.TryAddSingleton<ICalcRequestService, CalcRequestService>();
//services.TryAddSingleton<IFileService, FileService>();
//services.TryAddSingleton<IProdService, ProdService>();
return services;
}
}
}
+24
View File
@@ -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<MachDataItem> MtcDataItems
{
get => string.IsNullOrWhiteSpace(MtcDataItemsRaw) ? new List<MachDataItem>() : JsonSerializer.Deserialize<List<MachDataItem>>(MtcDataItemsRaw) ?? new();
set => MtcDataItemsRaw = JsonSerializer.Serialize(value);
}
}
}
@@ -0,0 +1,127 @@
// <auto-generated />
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<string>("IdxMacchina")
.HasColumnType("nvarchar(450)");
b.Property<string>("MtcDataItemsRaw")
.HasColumnType("nvarchar(max)");
b.HasKey("IdxMacchina");
b.ToTable("mtc_setup");
});
modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<double>("AvgDuration")
.HasColumnType("float");
b.Property<string>("Destination")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("Hour")
.HasColumnType("datetime2");
b.Property<string>("MachineId")
.HasColumnType("nvarchar(450)");
b.Property<double>("MaxDuration")
.HasColumnType("float");
b.Property<double>("MinDuration")
.HasColumnType("float");
b.Property<long>("NoReply")
.HasColumnType("bigint");
b.Property<long>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<double>("AvgDuration")
.HasColumnType("float");
b.Property<string>("Destination")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("Hour")
.HasColumnType("datetime2");
b.Property<double>("MaxDuration")
.HasColumnType("float");
b.Property<double>("MinDuration")
.HasColumnType("float");
b.Property<long>("NoReply")
.HasColumnType("bigint");
b.Property<long>("RequestCount")
.HasColumnType("bigint");
b.Property<string>("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
}
}
}
@@ -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<string>(type: "nvarchar(450)", nullable: false),
MtcDataItemsRaw = table.Column<string>(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");
}
}
}
@@ -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<string>("IdxMacchina")
.HasColumnType("nvarchar(450)");
b.Property<string>("MtcDataItemsRaw")
.HasColumnType("nvarchar(max)");
b.HasKey("IdxMacchina");
b.ToTable("mtc_setup");
});
modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b =>
{
b.Property<int>("Id")
+16 -17
View File
@@ -108,7 +108,6 @@ namespace MP.Data
public virtual DbSet<TksScoreModel> DbSetTksScore { get; set; }
public virtual DbSet<RemoteRebootLogModel> 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<StatsAnagArticoli>(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<AnagArticoliModel>(entity =>
{
entity.HasKey(e => e.CodArticolo);
+2
View File
@@ -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<StatsDetailModel> DbSetStatsDet { get; set; }
public virtual DbSet<StatsAggregatedModel> DbSetStatsAggr { get; set; }
public virtual DbSet<MtcSetupModel> DbSetMtcSetup { get; set; }
#endregion Public Properties
@@ -0,0 +1,13 @@
using MP.Data.DbModels.Mtc;
using System.Threading.Tasks;
namespace MP.Data.Repository.Mtc
{
public interface IMtcSetupRepository
{
Task<MtcSetupModel> GetByIdxAsync(string idxMacchina);
Task InsertAsync(MtcSetupModel newRec);
Task DeleteAsync(string idxMacchina);
Task UpdateAsync(MtcSetupModel updRec);
}
}
@@ -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<MoonPro_UtilsContext> ctxFactory) : base(ctxFactory)
{
}
#endregion Public Constructors
#region Public Methods
/// <inheritdoc />
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();
}
}
/// <inheritdoc />
public async Task<MtcSetupModel> GetByIdxAsync(string idxMacchina)
{
await using var dbCtx = await CreateContextAsync();
return await dbCtx.DbSetMtcSetup
.Include(s => s.MtcDataItems)
.FirstOrDefaultAsync(s => s.IdxMacchina == idxMacchina);
}
/// <inheritdoc />
public async Task InsertAsync(MtcSetupModel newRec)
{
await using var dbCtx = await CreateContextAsync();
dbCtx.DbSetMtcSetup.Add(newRec);
await dbCtx.SaveChangesAsync();
}
/// <inheritdoc />
public async Task UpdateAsync(MtcSetupModel updRec)
{
await using var dbCtx = await CreateContextAsync();
dbCtx.DbSetMtcSetup.Update(updRec);
await dbCtx.SaveChangesAsync();
}
#endregion Public Methods
}
}
+23
View File
@@ -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
{
/// <summary>
/// Replace the data set for the specified machine.
/// Deletes existing record then inserts new one.
/// </summary>
Task<bool> ReplaceMachineDataAsync(string idxMacchina, List<MachDataItem> items);
/// <summary>
/// Retrieve all data for a given machine.
/// </summary>
Task<MtcSetupModel> GetMachineDataAsync(string idxMacchina);
}
}
+60
View File
@@ -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;
}
/// <inheritdoc />
public async Task<bool> ReplaceMachineDataAsync(string idxMacchina, List<MachDataItem> 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;
});
}
/// <inheritdoc />
public async Task<MtcSetupModel> 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
);
});
}
}
}