diff --git a/MP.Data/DbModels/Utils/StatsAggregatedModel.cs b/MP.Data/DbModels/Utils/StatsAggregatedModel.cs
index ece10c4b..3ecf54ad 100644
--- a/MP.Data/DbModels/Utils/StatsAggregatedModel.cs
+++ b/MP.Data/DbModels/Utils/StatsAggregatedModel.cs
@@ -15,11 +15,16 @@ namespace MP.Data.DbModels.Utils
{
[Key]
public int Id { get; set; }
+
///
/// Ambiente di destinazione IOC/IO (new/old)
///
public string Destination { get; set; } = "";
///
+ /// ID Macchina di riferimento
+ ///
+ public string MachineId { get; set; } = "";
+ ///
/// DataOra riferimento
///
public DateTime Hour { get; set; }
diff --git a/MP.Data/Migrations/MoonPro_Utils/20260422155939_UpdateAggrStat.Designer.cs b/MP.Data/Migrations/MoonPro_Utils/20260422155939_UpdateAggrStat.Designer.cs
new file mode 100644
index 00000000..ab0d6df4
--- /dev/null
+++ b/MP.Data/Migrations/MoonPro_Utils/20260422155939_UpdateAggrStat.Designer.cs
@@ -0,0 +1,114 @@
+//
+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("20260422155939_UpdateAggrStat")]
+ partial class UpdateAggrStat
+ {
+ 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.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/20260422155939_UpdateAggrStat.cs b/MP.Data/Migrations/MoonPro_Utils/20260422155939_UpdateAggrStat.cs
new file mode 100644
index 00000000..2ceae2e4
--- /dev/null
+++ b/MP.Data/Migrations/MoonPro_Utils/20260422155939_UpdateAggrStat.cs
@@ -0,0 +1,47 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MP.Data.Migrations.MoonPro_Utils
+{
+ public partial class UpdateAggrStat : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "idx_statsaggr_env_hour",
+ table: "stats_aggr");
+
+ migrationBuilder.AddColumn(
+ name: "MachineId",
+ table: "stats_aggr",
+ type: "nvarchar(450)",
+ nullable: true);
+
+ migrationBuilder.CreateIndex(
+ name: "idx_statsaggr_env_mach_hour",
+ table: "stats_aggr",
+ columns: new[] { "Destination", "MachineId", "Hour" },
+ unique: true,
+ filter: "[Destination] IS NOT NULL AND [MachineId] IS NOT NULL");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "idx_statsaggr_env_mach_hour",
+ table: "stats_aggr");
+
+ migrationBuilder.DropColumn(
+ name: "MachineId",
+ table: "stats_aggr");
+
+ migrationBuilder.CreateIndex(
+ name: "idx_statsaggr_env_hour",
+ table: "stats_aggr",
+ columns: new[] { "Destination", "Hour" },
+ unique: true,
+ filter: "[Destination] IS NOT NULL");
+ }
+ }
+}
diff --git a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs
index ab41958b..f935fcb6 100644
--- a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs
+++ b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs
@@ -40,6 +40,9 @@ namespace MP.Data.Migrations.MoonPro_Utils
b.Property("Hour")
.HasColumnType("datetime2");
+ b.Property("MachineId")
+ .HasColumnType("nvarchar(450)");
+
b.Property("MaxDuration")
.HasColumnType("float");
@@ -54,10 +57,10 @@ namespace MP.Data.Migrations.MoonPro_Utils
b.HasKey("Id");
- b.HasIndex("Destination", "Hour")
+ b.HasIndex("Destination", "MachineId", "Hour")
.IsUnique()
- .HasDatabaseName("idx_statsaggr_env_hour")
- .HasFilter("[Destination] IS NOT NULL");
+ .HasDatabaseName("idx_statsaggr_env_mach_hour")
+ .HasFilter("[Destination] IS NOT NULL AND [MachineId] IS NOT NULL");
b.ToTable("stats_aggr");
});
diff --git a/MP.Data/MoonPro_UtilsContext.cs b/MP.Data/MoonPro_UtilsContext.cs
index 9b4eb6eb..bbcc6ac7 100644
--- a/MP.Data/MoonPro_UtilsContext.cs
+++ b/MP.Data/MoonPro_UtilsContext.cs
@@ -83,43 +83,12 @@ namespace MP.Data
.HasIndex(x => new { x.Destination, x.Type, x.Hour })
.HasDatabaseName("idx_statsdet_hour_env_type")
.IsUnique();
+
modelBuilder.Entity()
- .HasIndex(x => new { x.Destination, x.Hour })
- .HasDatabaseName("idx_statsaggr_env_hour")
+ .HasIndex(x => new { x.Destination, x.MachineId, x.Hour })
+ .HasDatabaseName("idx_statsaggr_env_mach_hour")
.IsUnique();
- // modelBuilder.Entity(entity =>
- // {
- // entity.HasKey(e => e.CodArticolo);
-
- // entity.ToView("AnagArticoli");
-
- // entity.Property(e => e.CodArticolo)
- // .IsRequired()
- // .HasMaxLength(50);
-
- // entity.Property(e => e.DescArticolo)
- // .IsRequired()
- // .HasMaxLength(250);
-
- // entity.Property(e => e.Disegno)
- // .IsRequired()
- // .HasMaxLength(50);
-
- // entity.Property(e => e.Tipo)
- // .IsRequired()
- // .HasMaxLength(50);
-
- // entity.Property(e => e.Azienda)
- // .IsRequired()
- // .HasMaxLength(50);
- // });
-
- // modelBuilder.Entity(entity =>
- // {
- // entity.HasKey(e => new { e.IdxMacchina, e.CodFlux });
- // });
-
OnModelCreatingPartial(modelBuilder);
}
diff --git a/MP.Data/Repository/Utils/StatsAggrRepository.cs b/MP.Data/Repository/Utils/StatsAggrRepository.cs
index a2ad622d..22fd2f55 100644
--- a/MP.Data/Repository/Utils/StatsAggrRepository.cs
+++ b/MP.Data/Repository/Utils/StatsAggrRepository.cs
@@ -93,13 +93,13 @@ namespace MP.Data.Repository.Utils
// Creiamo un dizionario per ricerca rapida O(1) basato sulla chiave univoca (Dest + Hour)
// Usiamo una Tupla come chiave del dizionario
var lookup = existingRecords.ToDictionary(
- x => (x.Destination, x.Hour),
+ x => (x.Destination, x.MachineId, x.Hour),
x => x
);
foreach (var incoming in listRecords)
{
- var key = (incoming.Destination, incoming.Hour);
+ var key = (incoming.Destination, incoming.MachineId, incoming.Hour);
if (lookup.TryGetValue(key, out var existing))
{
// --- CASO: UPDATE ---
@@ -134,57 +134,6 @@ namespace MP.Data.Repository.Utils
}
}
-#if false
- ///
- public async Task UpsertManyAsyncOrig(List listRecords, bool removeOld)
- {
- int answ = 0;
- await using var dbCtx = await CreateContextAsync();
- await using var tx = await dbCtx.Database.BeginTransactionAsync();
- try
- {
- // in primis se richiesto calcolo range periodo e svuoto...
- if (removeOld)
- {
- var firstRec = listRecords.OrderBy(x => x.Hour).FirstOrDefault();
- var lastRec = listRecords.OrderByDescending(x => x.Hour).FirstOrDefault();
-
- if (firstRec != null && lastRec != null)
- {
- DateTime startDate = firstRec.Hour;
- DateTime endDate = lastRec.Hour;
-
- var items = await dbCtx.DbSetStatsAggr
- .Where(x => x.Hour >= startDate && x.Hour <= endDate)
- .ToListAsync();
-
- dbCtx.DbSetStatsAggr.RemoveRange(items);
- await dbCtx.SaveChangesAsync();
- }
- }
-
- await dbCtx
- .DbSetStatsAggr
- .AddRangeAsync(listRecords);
-
- // salvo!
- answ = await dbCtx.SaveChangesAsync();
-
- // commit transazione
- await tx.CommitAsync();
-
- // libero memoria del changeTracker
- dbCtx.ChangeTracker.Clear();
- return answ;
- }
- catch
- {
- await tx.RollbackAsync();
- throw;
- }
- }
-#endif
-
#endregion Public Methods
#region Protected Fields
diff --git a/MP.IOC/Components/Compo/ParetoDetail.razor b/MP.IOC/Components/Compo/ParetoDetail.razor
index d9e1ece9..268dc234 100644
--- a/MP.IOC/Components/Compo/ParetoDetail.razor
+++ b/MP.IOC/Components/Compo/ParetoDetail.razor
@@ -1,6 +1,6 @@
-