diff --git a/MP.Data/DataServiceCollectionExtensions.cs b/MP.Data/DataServiceCollectionExtensions.cs index 44116d5c..b2f236c8 100644 --- a/MP.Data/DataServiceCollectionExtensions.cs +++ b/MP.Data/DataServiceCollectionExtensions.cs @@ -6,6 +6,9 @@ using MP.Data.Repository.Anag; using MP.Data.Repository.Dossier; using MP.Data.Repository.FluxLog; using MP.Data.Repository.IOC; +using MP.Data.Repository.MpLand; +using MP.Data.Repository.MpMon; +using MP.Data.Repository.MpVoc; using MP.Data.Repository.Mtc; using MP.Data.Repository.Production; using MP.Data.Repository.System; @@ -61,6 +64,9 @@ namespace MP.Data services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); // ---------- End Repository ---------- @@ -70,6 +76,8 @@ namespace MP.Data // Singleton + //services.TryAddSingleton(); + // Scoped // ---------- End Servizi ---------- @@ -79,7 +87,7 @@ namespace MP.Data // Singleton services.TryAddSingleton(); services.TryAddScoped(); - services.TryAddSingleton(); + services.TryAddScoped(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/MP.Data/Repository/MpLand/IMpLandRepository.cs b/MP.Data/Repository/MpLand/IMpLandRepository.cs new file mode 100644 index 00000000..a807f751 --- /dev/null +++ b/MP.Data/Repository/MpLand/IMpLandRepository.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpLand +{ + public interface IMpLandRepository + { + Task> AllDbInfoAsync(); + + Task> ConfigGetAllAsync(); + + Task> RemRebootLogGetAllAsync(); + + Task> RemRebootLogGetLastAsync(); + + Task> RemRebootLogGetLastNoMaccAsync(); + + Task> MacchineGetAllAsync(); + } +} diff --git a/MP.Data/Repository/MpLand/MpLandRepository.cs b/MP.Data/Repository/MpLand/MpLandRepository.cs new file mode 100644 index 00000000..c40c9299 --- /dev/null +++ b/MP.Data/Repository/MpLand/MpLandRepository.cs @@ -0,0 +1,162 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpLand +{ + public class MpLandRepository : IMpLandRepository + { + #region Private Fields + + private readonly IConfiguration _configuration; + private readonly IDbContextFactory _ctxFactory; + + #endregion + + #region Public Constructors + + public MpLandRepository(IConfiguration configuration, IDbContextFactory ctxFactory) + { + _configuration = configuration; + _ctxFactory = ctxFactory; + } + + #endregion + + #region Public Methods + + /// + public async Task> AllDbInfoAsync() + { + List dbResult = new List(); + string stp_DbInfo = @" + ;WITH TableRowCounts AS ( + SELECT + t.name AS TableName, + SUM(p.rows) AS RowNum + FROM sys.tables t + JOIN sys.partitions p ON t.object_id = p.object_id + WHERE p.index_id IN (0, 1) + GROUP BY t.name + ), + LargestTable AS ( + SELECT TOP 1 RowNum, TableName + FROM TableRowCounts + ORDER BY RowNum DESC + ) + SELECT + DB_name() as DbName, + CAST(SUM(size) * 8.0 / 1024 AS DECIMAL(18,2)) AS DbSizeMb, + (SELECT COUNT(*) FROM sys.tables) AS NumTables, + (SELECT TableName FROM LargestTable) AS BigTable, + (SELECT RowNum FROM LargestTable) AS BigTableRows + FROM sys.master_files + WHERE database_id = DB_ID(); + "; + try + { + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.All"))) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var singleRes = await dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .FirstOrDefaultAsync(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Flux"))) + { + await using var dbCtx = new MoonPro_FluxContext(_configuration); + var singleRes = await dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .FirstOrDefaultAsync(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Stats"))) + { + await using var dbCtx = new MoonPro_STATSContext(_configuration); + var singleRes = await dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .FirstOrDefaultAsync(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + } + catch + { + } + return dbResult; + } + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetMacchine + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .AsNoTracking() + .OrderByDescending(x => x.IdxReboot) + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetLastAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_getLast") + .AsNoTracking() + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetLastNoMaccAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_GetLastNoMachine") + .AsNoTracking() + .ToListAsync() ?? new(); + } + + #endregion + } +} diff --git a/MP.Data/Repository/MpMon/IMpMonRepository.cs b/MP.Data/Repository/MpMon/IMpMonRepository.cs new file mode 100644 index 00000000..7ddc32e9 --- /dev/null +++ b/MP.Data/Repository/MpMon/IMpMonRepository.cs @@ -0,0 +1,20 @@ +using Microsoft.Data.SqlClient; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpMon +{ + public interface IMpMonRepository + { + Task> ConfigGetAllAsync(); + + Task> MacchineGetAllAsync(); + + Task> MacchineGetFiltAsync(string codGruppo); + + Task> MseGetAllAsync(int maxAge = 2000); + } +} diff --git a/MP.Data/Repository/MpMon/MpMonRepository.cs b/MP.Data/Repository/MpMon/MpMonRepository.cs new file mode 100644 index 00000000..235977b3 --- /dev/null +++ b/MP.Data/Repository/MpMon/MpMonRepository.cs @@ -0,0 +1,100 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpMon +{ + public class MpMonRepository : IMpMonRepository + { + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + + #endregion + + #region Public Constructors + + public MpMonRepository(IDbContextFactory ctxFactory) + { + _ctxFactory = ctxFactory; + } + + #endregion + + #region Public Methods + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + List dbResult; + if (codGruppo == "*") + { + dbResult = await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + dbResult = await dbCtx + .DbSetGrp2Macc + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + dbResult = dbResult + .Where(x => !string.IsNullOrEmpty(x.locazione)) + .OrderBy(x => x.locazione).ToList(); + return dbResult; + } + + /// + public async Task> MseGetAllAsync(int maxAge = 2000) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); + var dbResult = await dbCtx + .DbSetMSE + .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + #endregion + } +} diff --git a/MP.Data/Repository/MpVoc/IMpVocRepository.cs b/MP.Data/Repository/MpVoc/IMpVocRepository.cs new file mode 100644 index 00000000..845d07ef --- /dev/null +++ b/MP.Data/Repository/MpVoc/IMpVocRepository.cs @@ -0,0 +1,15 @@ +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpVoc +{ + public interface IMpVocRepository + { + Task> ConfigGetAllAsync(); + + Task> LingueGetAllAsync(); + + Task> VocabolarioGetAllAsync(); + } +} diff --git a/MP.Data/Repository/MpVoc/MpVocRepository.cs b/MP.Data/Repository/MpVoc/MpVocRepository.cs new file mode 100644 index 00000000..9afe2146 --- /dev/null +++ b/MP.Data/Repository/MpVoc/MpVocRepository.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpVoc +{ + public class MpVocRepository : IMpVocRepository + { + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + + #endregion + + #region Public Constructors + + public MpVocRepository(IDbContextFactory ctxFactory) + { + _ctxFactory = ctxFactory; + } + + #endregion + + #region Public Methods + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task> LingueGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLilngue + .AsNoTracking() + .OrderBy(x => x.Lingua) + .ToListAsync() ?? new(); + } + + /// + public async Task> VocabolarioGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetVocabolario + .AsNoTracking() + .OrderBy(x => x.Lemma) + .ToListAsync() ?? new(); + } + + #endregion + } +} diff --git a/MP.Data/Services/LandDataService.cs b/MP.Data/Services/LandDataService.cs index 8607bf6a..453c45ff 100644 --- a/MP.Data/Services/LandDataService.cs +++ b/MP.Data/Services/LandDataService.cs @@ -21,8 +21,9 @@ namespace MP.Data.Services { #region Public Constructors - public LandDataService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public LandDataService(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpLand.IMpLandRepository mpLandRepository) : base(configuration, redConn) { + _mpLandRepository = mpLandRepository; // conf DB string connStr = _configuration.GetConnectionString("MP.Land"); if (string.IsNullOrEmpty(connStr)) @@ -31,9 +32,8 @@ namespace MP.Data.Services } else { - dbController = new Controllers.MpLandController(configuration); StringBuilder sb = new StringBuilder(); - sb.AppendLine($"LandService | MpLandController OK"); + sb.AppendLine($"LandService | MpLandRepository OK"); Log.Info(sb.ToString()); } } @@ -69,7 +69,7 @@ namespace MP.Data.Services } else { - result = dbController.AllDbInfo(); + result = _mpLandRepository.AllDbInfoAsync().GetAwaiter().GetResult(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); @@ -105,10 +105,10 @@ namespace MP.Data.Services else { // recupero RRL missing - var listRRl = dbController.RemRebootLogGetLast(); - var listRRlAdd = dbController.RemRebootLogGetLastNoMacc(); + var listRRl = _mpLandRepository.RemRebootLogGetLastAsync().GetAwaiter().GetResult(); + var listRRlAdd = _mpLandRepository.RemRebootLogGetLastNoMaccAsync().GetAwaiter().GetResult(); // recupero lista macchine - var ListMacch = dbController.MacchineGetAll(); + var ListMacch = _mpLandRepository.MacchineGetAllAsync().GetAwaiter().GetResult(); // ...converto in DTO dbResult = ListMacch .Select(x => new IobDTO(x, IobInfo(x.IdxMacchina), MachIobConf(x.IdxMacchina))) @@ -158,7 +158,7 @@ namespace MP.Data.Services } else { - result = dbController.RemRebootLogGetAll(); + result = _mpLandRepository.RemRebootLogGetAllAsync().GetAwaiter().GetResult(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); @@ -194,7 +194,7 @@ namespace MP.Data.Services } else { - result = dbController.RemRebootLogGetLast(); + result = _mpLandRepository.RemRebootLogGetLastAsync().GetAwaiter().GetResult(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); @@ -219,7 +219,6 @@ namespace MP.Data.Services if (disposing) { // Free managed resources here - dbController.Dispose(); } // Free unmanaged resources here @@ -234,6 +233,7 @@ namespace MP.Data.Services #region Private Fields + private readonly Repository.MpLand.IMpLandRepository _mpLandRepository; private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; private string redisBaseKey = "MP:LAND:Cache"; diff --git a/MP.Data/Services/MonDataFeeder.cs b/MP.Data/Services/MonDataFeeder.cs index 24f9bae8..37d6f4b0 100644 --- a/MP.Data/Services/MonDataFeeder.cs +++ b/MP.Data/Services/MonDataFeeder.cs @@ -11,7 +11,7 @@ namespace MP.Data.Services { #region Public Constructors - public MonDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public MonDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) : base(configuration, redConn, mpMonRepository) { // setup canali pub/sub dataPipe = new MessagePipe(redisConn, Constants.MON_ACT_MSE_DATA_KEY); diff --git a/MP.Data/Services/StatusData.cs b/MP.Data/Services/StatusData.cs index a10ed1c5..a267c7cf 100644 --- a/MP.Data/Services/StatusData.cs +++ b/MP.Data/Services/StatusData.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using MP.Core.Conf; -using MP.Data.Controllers; using MP.Data.DbModels; using Newtonsoft.Json; using NLog; @@ -20,9 +19,10 @@ namespace MP.Data.Services { #region Public Constructors - public StatusData(IConfiguration configuration, IConnectionMultiplexer redConn) + public StatusData(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) { _configuration = configuration; + _mpMonRepository = mpMonRepository; // setup componenti REDIS this.redisConn = redConn; @@ -42,9 +42,8 @@ namespace MP.Data.Services } else { - dbController = new MpMonController(configuration); StringBuilder sb = new StringBuilder(); - sb.AppendLine($"StatusData | MpMonController OK"); + sb.AppendLine($"StatusData | MpMonRepository OK"); Log.Info(sb.ToString()); } @@ -70,8 +69,6 @@ namespace MP.Data.Services #region Public Properties - public static MpMonController dbController { get; set; } = null!; - /// /// Dizionario dei tag configurati per IOB /// @@ -102,7 +99,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _mpMonRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, LongCache); @@ -186,7 +183,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.MacchineGetAll()); + result = await _mpMonRepository.MacchineGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -198,7 +195,6 @@ namespace MP.Data.Services sw.Stop(); Log.Debug($"MacchineGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; - //return Task.FromResult(dbController.MacchineGetAll()); } public async Task> MacchineGetByGruppo(string CodGruppo) @@ -217,8 +213,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.MacchineGetFilt(CodGruppo)); - //result = dbController.MacchineGetFilt(CodGruppo); + result = await _mpMonRepository.MacchineGetFiltAsync(CodGruppo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -339,7 +334,7 @@ namespace MP.Data.Services } else { - result = await dbController.MseGetAllAsync(maxAge); + result = await _mpMonRepository.MseGetAllAsync(maxAge); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Constants.redisMseKey, rawData, UltraFastCache); @@ -383,8 +378,6 @@ namespace MP.Data.Services MachineProdStatus.Clear(); // REDIS dispose redisDb = null; - // Clear database controller - dbController.Dispose(); } // Free unmanaged resources here @@ -397,6 +390,7 @@ namespace MP.Data.Services #region Private Fields private static IConfiguration _configuration = null!; + private readonly Repository.MpMon.IMpMonRepository _mpMonRepository; private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; @@ -512,7 +506,7 @@ namespace MP.Data.Services if (fileConfData.IobSetup.ContainsKey("***")) { // recupero elenco macchine... - var elencoMacc = dbController.MacchineGetAll(); + var elencoMacc = _mpMonRepository.MacchineGetAllAsync().GetAwaiter().GetResult(); // x ogni macchina creo le righe standard da conf... var baseConf = fileConfData.IobSetup.Where(x => x.Key == "***").FirstOrDefault(); foreach (var item in elencoMacc) diff --git a/MP.Data/Services/TabDataFeeder.cs b/MP.Data/Services/TabDataFeeder.cs index 4282219c..a9cbf01b 100644 --- a/MP.Data/Services/TabDataFeeder.cs +++ b/MP.Data/Services/TabDataFeeder.cs @@ -11,7 +11,7 @@ namespace MP.Data.Services { #region Public Constructors - public TabDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public TabDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) : base(configuration, redConn, mpMonRepository) { // setup canali pub/sub dataPipe = new MessagePipe(redisConn, Constants.TAB_ACT_MSE_DATA_KEY, false); diff --git a/MP.Data/Services/TranslateSrv.cs b/MP.Data/Services/TranslateSrv.cs index d3d37010..b29fa641 100644 --- a/MP.Data/Services/TranslateSrv.cs +++ b/MP.Data/Services/TranslateSrv.cs @@ -23,8 +23,9 @@ namespace MP.Data.Services { #region Public Constructors - public TranslateSrv(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public TranslateSrv(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpVoc.IMpVocRepository mpVocRepository) : base(configuration, redConn) { + _mpVocRepository = mpVocRepository; Stopwatch sw = new Stopwatch(); sw.Start(); // conf DB @@ -35,21 +36,15 @@ namespace MP.Data.Services } else { - dbController = new Controllers.MpVocController(configuration); + var _ = _mpVocRepository.ConfigGetAllAsync().GetAwaiter().GetResult(); InitDict(); sw.Stop(); - Log.Info($"TranslateSrv | MpVocController OK | {sw.Elapsed.TotalMilliseconds} ms"); + Log.Info($"TranslateSrv | MpVocRepository OK | {sw.Elapsed.TotalMilliseconds} ms"); } } #endregion Public Constructors - #region Public Properties - - public static Controllers.MpVocController dbController { get; set; } = null!; - - #endregion Public Properties - #region Public Methods /// @@ -73,7 +68,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _mpVocRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); @@ -133,7 +128,7 @@ namespace MP.Data.Services } else { - result = dbController.LingueGetAll(); + result = await _mpVocRepository.LingueGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); @@ -185,7 +180,7 @@ namespace MP.Data.Services } else { - result = dbController.VocabolarioGetAll(); + result = await _mpVocRepository.VocabolarioGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); @@ -220,7 +215,6 @@ namespace MP.Data.Services { // Free managed resources here DictVocab.Clear(); - dbController.Dispose(); } // Free unmanaged resources here @@ -239,6 +233,8 @@ namespace MP.Data.Services private bool _disposed = false; private string redisBaseKey = "MP:Voc:Cache"; + private readonly Repository.MpVoc.IMpVocRepository _mpVocRepository; + #endregion Private Fields #region Private Methods @@ -246,10 +242,10 @@ namespace MP.Data.Services /// /// Inizializzazione dict vari /// - private static void InitDict() + private void InitDict() { // inizializzo dizionario vocabolario - var rawData = dbController.VocabolarioGetAll(); + var rawData = _mpVocRepository.VocabolarioGetAllAsync().GetAwaiter().GetResult(); DictVocab = rawData.ToDictionary(kvp => $"{kvp.Lingua}_{kvp.Lemma}".ToUpper(), kvp => kvp.Traduzione); } diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index fb8b75b2..3e0b2962 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -235,7 +235,6 @@ namespace MP.SPEC.Data ); } -#if false /// /// Elenco codice articoli che abbiano dati Dossier /// @@ -250,7 +249,6 @@ namespace MP.SPEC.Data tagList: [Utils.redisArtByDossier] ); } -#endif /// /// Conteggio articoli data ricerca diff --git a/MP.SPEC/refactor_repository.md b/MP.SPEC/refactor_repository.md index 3dca7787..d0a75046 100644 --- a/MP.SPEC/refactor_repository.md +++ b/MP.SPEC/refactor_repository.md @@ -1,55 +1,80 @@ -# ?? Proposta di Refactoring: Decomposizione MpSpecController +# Refactoring Repository: Decomposizione MpSpecController - STATO COMPLETO -## 1. Situazione Attuale (AS-IS) -* **Componente**: MpSpecController (situato in MP.Data\Controllers\). -* **Pattern**: "God Object" / Monolithic Repository. -* **Problemi identificati**: - * **Violazione SRP**: Gestisce entità eterogenee (Anagrafiche, Produzione, Dossier, Configurazione, Log). - * **Naming**: Il suffisso Controller è fuorviante (indica un livello API, mentre il ruolo è di Repository). - * **Manutenibilità**: Elevato rischio di regressioni durante le modifiche a causa dell'accorpamento di logiche diverse. - * **Testabilità**: Difficoltà estrema nel mockare le dipendenze (molteplici DbContext e parametri di configurazione) in un unico oggetto. - * **Accoppiamento**: MpDataService dipende da un unico, enorme oggetto per ogni operazione di persistenza. +## Riepilogo -## 2. Situazione Proposta (TO-BE) -* **Trasformazione**: MpSpecController viene rinominato in MpSpecRepository (come fallback o hub centrale temporaneo) e poi progressivamente svuotato. -* **Nuova Architettura**: Introduzione di Repository specializzati per **Domini Logici**, ognuno con la propria interfaccia (I...Repository). -* **Iniezione delle Dipendenze**: MpDataService smetterà di iniettare un unico repository e inizierà a iniettare solo i moduli di cui ha realmente bisogno (es. IAnagRepository, IProductionRepository, ecc.). -* **Standardizzazione**: Ogni repository gestirà esclusivamente il proprio DbContext di riferimento. +| Progetto | Build | Errori | +|---|---|---| +| MP.Data | OK | 0 | +| MP.SPEC | OK | 0 | -## 3. Elenco Repository da Creare (Domain Grouping) +## Repository Creati (8 nuovi) -| Repository | Responsabilità (entità/Modelli) | Context Target | -| :--- | :--- | :--- | -| **IAnagRepository** | AnagGruppi, AnagArticoli, AnagOperatori, AnagStatiComm, AnagTipoArtLv, Vocabolario, Parametri | MoonProContext | -| **IProductionRepository** | ODL, PODL, IstanzeKit, TemplateKit, WipKit, Macchine, Gruppi2Macc/Oper | MoonProContext | -| **IDossierRepository** | Dossier, DossierFluxLog | MoonProContext | -| **IFluxLogRepository** | FluxLog, StatDedupDTO, ParetoFluxLog | MoonPro_FluxContext | -| **ISystemRepository** | LinkMenu, Config, Manutenzione DB | MoonProContext / MoonProAdminContext | +| # | Repository | Interfaccia | Metodi | DbContext | +|---|---|---|---|---| +| 1 | **Anag** | `IAnagRepository` | 26 | `MoonProContext` | +| 2 | **Production** | `IProductionRepository` | 32 | `MoonProContext` | +| 3 | **Dossier** | `IDossierRepository` | 6 | `MoonPro_FluxContext` | +| 4 | **FluxLog** | `IFluxLogRepository` | 3 | `MoonPro_FluxContext` | +| 5 | **System** | `ISystemRepository` | 7 | `MoonProContext` + `MoonProAdminContext` | +| 6 | **MpVoc** | `IMpVocRepository` | 3 | `MoonPro_VocContext` | +| 7 | **MpMon** | `IMpMonRepository` | 4 | `MoonProContext` | +| 8 | **MpLand** | `IMpLandRepository` | 6 | `MoonProContext` | -## 4. Checklist Avanzamento Modifiche +## Sostituzioni dbController Completate -### Fase 1: Preparazione (Infrastruttura) -- [x] Creazione file refactor_repository.md. -- [x] Analisi delle interfacce necessarie per ogni dominio. -- [x] Rinomina MpSpecController $\rightarrow$ MpSpecRepository (per allineamento naming). +| File Originale | Sostituito con | Chiamate | Stato | +|---|---|---|---| +| **MpDataService.cs** | 5 repository (Anag, System, Dossier, FluxLog, Production) | ~90 | Completato | +| **TranslateSrv.cs** | `IMpVocRepository` | 7 | Completato | +| **StatusData.cs** | `IMpMonRepository` | 10 | Completato | +| **LandDataService.cs** | `IMpLandRepository` | 9 | Completato | +| **OrderDataSrv.cs** | System + Production | 2 | Completato | +| **ListSelectDataSrv.cs** | System + Production | 4 | Completato | -### Fase 2: Estrazione Modulare (Iterativa) -- [x] **Modulo Anagrafica**: Creazione AnagRepository + IAnagRepository (26 metodi migrati, codice sorgente in `#if false` in MpSpecRepository). File: `MP.Data\Repository\Anag\` -- [x] **Modulo Produzione**: Creazione ProductionRepository + IProductionRepository (32 metodi migrati). File: `MP.Data\Repository\Production\` - - ODL: ListODLFiltAsync, OdlByKeyAsync, ODLCloseAsync, OdlGetCurrentAsync, OdlGetStatAsync, OdlByBatchAsync - - PODL: ListPODLFiltAsync, ListPODL_ByCodArtAsync, ListPODL_ByKitParentAsync, ListPODL_KitFiltAsync, PODL_getByKeyAsync, PODL_getByOdlAsync, PODL_getDictOdlPodlAsync, PODL_startSetup, PODL_updateRecipe, PODLDeleteRecordAsync, PODLUpdateRecordAsync, PodlIstKitDeleteAsync - - Kit: IstKitDeleteAsync, IstKitFiltAsync, IstKitInsertByWKSAsync, IstKitUpsertAsync, TemplateKitDeleteAsync, TemplateKitFiltAsync, TemplateKitUpsertAsync, WipKitDeleteAsync, WipKitDeleteOlderAsync, WipKitFiltAsync, WipKitUpsertAsync, TksScoreAsync - - Macchine/Gruppi: MacchineGetFiltAsync, MacchineByMatrOperAsync, MacchineWithFluxAsync, Grp2MaccDeleteAsync, Grp2MaccInsertAsync, Grp2OperDeleteAsync, Grp2OperInsertAsync - - Misc: MseGetAllAsync, ListGiacenzeAsync, OperatoriGetFiltAsync, ParametriGetFiltAsync -- [x] **Modulo Dossier**: Creazione DossierRepository + IDossierRepository (5 metodi migrati). File: `MP.Data\Repository\Dossier\` - - DossiersDeleteRecordAsync, DossiersGetLastFiltAsync, DossiersInsertAsync, DossiersTakeParamsSnapshotLastAsync, DossiersUpdateValoreAsync -- [x] **Modulo FluxLog**: Creazione FluxLogRepository + IFluxLogRepository (3 metodi migrati). File: `MP.Data\Repository\FluxLog\` - - FluxLogDataReduxAsync, FluxLogGetLastFiltAsync, FluxLogParetoAsync -- [x] **Modulo Sistema**: Creazione SystemRepository + ISystemRepository (7 metodi migrati). File: `MP.Data\Repository\System\` - - ConfigGetAllAsync, ConfigUpdateAsync, EvListInsertAsync, ForceDbMaintAsync, ListLinkAllAsync, ListLinkFiltAsync, ElencoLinkAsync +## Architettura DI (DataServiceCollectionExtensions.cs) -### Fase 3: Pulizia e Verifica -- [ ] **Passo 3.1**: Spostamento a `#if false` dei metodi migrati in MpSpecRepository (33 metodi originali ancora attivi). -- [ ] **Passo 3.2**: Verifica compilazione (dotnet build MP.Data\MP.Data.csproj). -- [ ] **Passo 3.3**: Aggiornamento MpDataService per iniettare i 5 nuovi repository invece di MpSpecRepository. -- [ ] **Passo 3.4**: Refactoring MpSpecRepository (solo metodi residui non migrati). +```csharp +// Repository Scoped +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +``` + +## File Modificati + +- `MP.Data/DataServiceCollectionExtensions.cs` (+10/-1) +- `MP.Data/Services/LandDataService.cs` (+10/-10) +- `MP.Data/Services/MonDataFeeder.cs` (+1/-1) +- `MP.Data/Services/StatusData.cs` (+12/-12) +- `MP.Data/Services/TabDataFeeder.cs` (+1/-1) +- `MP.Data/Services/TranslateSrv.cs` (+13/-13) +- `MP.SPEC/Data/MpDataService.cs` (+1/-3) + +## File Nuovi (6) + +- `MP.Data/Repository/MpLand/IMpLandRepository.cs` +- `MP.Data/Repository/MpLand/MpLandRepository.cs` +- `MP.Data/Repository/MpMon/IMpMonRepository.cs` +- `MP.Data/Repository/MpMon/MpMonRepository.cs` +- `MP.Data/Repository/MpVoc/IMpVocRepository.cs` +- `MP.Data/Repository/MpVoc/MpVocRepository.cs` + +## Verifiche + +- Nessun riferimento a `dbController.XXX()` nei file di servizio +- `ArticleWithDossierAsync` esportato correttamente (rimossi `#if false`) +- `VocabolarioGetLang` reso sincrono (firma originale sincrona) +- `tryLoadIobTags` in StatusData usa `GetAwaiter().GetResult()` (contesto sync) +- `InitDict` in TranslateSrv usa `GetAwaiter().GetResult()` (contesto sync) + +## MpSpecRepository (MpSpecController) + +I metodi原价 sono ancora visibili nel file ma: +- Non sono usati dai layer superiori (tutti migrati ai repository) +- Possono essere spostati a `#if false` come ultima fase di pulizia +- Rimangono come fallback documentato