Altra ottimizzazione letture cache async

This commit is contained in:
Samuele Locatelli
2026-05-28 18:59:54 +02:00
parent 6b49cb29fe
commit 37044040c4
9 changed files with 91 additions and 74 deletions
+16 -18
View File
@@ -1433,26 +1433,24 @@ namespace MP.Data.Controllers
/// <param name="startDate">Data inizio</param>
/// <param name="endDate">Data fine</param>
/// <returns></returns>
public List<ODLExpModel> ListODLFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate)
public async Task<List<ODLExpModel>> ListODLFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate)
{
List<ODLExpModel> dbResult = new List<ODLExpModel>();
using (var dbCtx = new MoonProContext(options))
{
var InCorso = new SqlParameter("@InCorso", inCorso);
var CodArt = new SqlParameter("@CodArt", codArt);
var KeyRich = new SqlParameter("@KeyRich", keyRichPart);
var CodGruppo = new SqlParameter("@CodGruppo", Reparto);
var IdxMacc = new SqlParameter("@IdxMacchina", IdxMacchina);
var DataFrom = new SqlParameter("@DataFrom", startDate);
var DataTo = new SqlParameter("@DataTo", endDate);
using var dbCtx = new MoonProContext(options);
dbResult = dbCtx
.DbSetODLExp
.FromSqlRaw("EXEC stp_ODL_getByFiltSpec @InCorso, @CodArt, @KeyRich, @CodGruppo, @IdxMacchina, @DataFrom, @DataTo", InCorso, CodArt, KeyRich, CodGruppo, IdxMacc, DataFrom, DataTo)
.AsNoTracking()
.ToList();
}
return dbResult;
var InCorso = new SqlParameter("@InCorso", inCorso);
var CodArt = new SqlParameter("@CodArt", codArt);
var KeyRich = new SqlParameter("@KeyRich", keyRichPart);
var CodGruppo = new SqlParameter("@CodGruppo", Reparto);
var IdxMacc = new SqlParameter("@IdxMacchina", IdxMacchina);
var DataFrom = new SqlParameter("@DataFrom", startDate);
var DataTo = new SqlParameter("@DataTo", endDate);
return await dbCtx
.DbSetODLExp
.FromSqlRaw("EXEC stp_ODL_getByFiltSpec @InCorso, @CodArt, @KeyRich, @CodGruppo, @IdxMacchina, @DataFrom, @DataTo", InCorso, CodArt, KeyRich, CodGruppo, IdxMacc, DataFrom, DataTo)
.AsNoTracking()
.ToListAsync();
}
/// <summary>
@@ -2206,7 +2204,7 @@ namespace MP.Data.Controllers
/// </summary>
/// <param name="missingIds"></param>
/// <returns></returns>
public async Task<Dictionary<int, int>> PODL_getDictOdlPodl(List<int> missingIds)
public async Task<Dictionary<int, int>> PODL_getDictOdlPodlAsync(List<int> missingIds)
{
if (missingIds == null || !missingIds.Any())
return new Dictionary<int, int>();
+2 -2
View File
@@ -109,7 +109,7 @@ namespace MP.Data.Services
}
else
{
result = await Task.FromResult(dbController.ListODLFilt(inCorso, CodArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate));
result = await dbController.ListODLFiltAsync(inCorso, CodArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate);
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await _redisDb.StringSetAsync(currKey, rawData, LongCache);
@@ -119,7 +119,7 @@ namespace MP.Data.Services
result = new List<ODLExpModel>();
}
sw.Stop();
Log.Debug($"ListODLFilt | CodArt: {CodArt} | IdxMacchina: {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms");
Log.Debug($"ListODLFiltAsync | CodArt: {CodArt} | IdxMacchina: {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
+1 -1
View File
@@ -76,7 +76,7 @@ namespace MP.SPEC.Components
{
DateTime oggi = DateTime.Today;
// recupero idxMaccSel x ODL...
var elencoOdl = await MDService.OdlListGetFilt(true, "*", "*", "*", "*", DateTime.Today.AddMonths(-1), DateTime.Today.AddDays(1));
var elencoOdl = await MDService.OdlListGetFiltAsync(true, "*", "*", "*", "*", DateTime.Today.AddMonths(-1), DateTime.Today.AddDays(1));
var currOdl = elencoOdl.FirstOrDefault(x => x.IdxOdl == idxOdl);
if (currOdl != null && currOdl.IdxOdl == idxOdl)
{
+13 -23
View File
@@ -78,8 +78,8 @@ namespace MP.SPEC.Components
#region Protected Fields
protected string selAzienda = "*";
protected string giacenzeConf = "false";
protected string selAzienda = "*";
#endregion Protected Fields
@@ -229,22 +229,10 @@ namespace MP.SPEC.Components
ListStati = await MDService.AnagStatiCommAsync();
selAzienda = await MDService.ConfigTryGetAsync("AZIENDA");
giacenzeConf = await MDService.ConfigTryGetAsync("SPEC_ShowGiacenze");
#if false
ListArticoli = await MDService.ArticoliGetSearchAsync(100000, "*", selAzienda, "");
#endif
ListMacchine = await MDService.MacchineGetFiltAsync("*");
await ReloadData(true);
}
/// <summary>
/// Ricerca articoli
/// </summary>
private string SearchArt = "";
/// <summary>
/// Num min car x ricerca
/// </summary>
private int SearchMinChar = 3;
protected override async Task OnParametersSetAsync()
{
if (!lastFilter.Equals(SelFilter))
@@ -277,7 +265,6 @@ namespace MP.SPEC.Components
if (alert)
{
await Task.Delay(1);
if (currRecord != null)
{
// serializzo valore x flux log...
@@ -288,8 +275,7 @@ namespace MP.SPEC.Components
await MDService.DossiersUpdateValore(currRecord);
currFluxLogDto = null;
isEditing = false;
await Task.Delay(1);
StateHasChanged();
await InvokeAsync(StateHasChanged);
}
return;
}
@@ -320,16 +306,19 @@ namespace MP.SPEC.Components
private DossierModel? currRecordClone = null;
#if false
private List<AnagArticoliModel>? ListArticoli;
#endif
private List<AnagGruppiModel>? ListGruppiFase;
private List<MacchineModel>? ListMacchine;
private List<DossierModel>? ListRecords;
private List<ListValuesModel>? ListStati;
/// <summary>
/// Ricerca articoli
/// </summary>
private string SearchArt = "";
private List<DossierModel>? SearchRecords;
#endregion Private Fields
@@ -354,6 +343,11 @@ namespace MP.SPEC.Components
private List<FluxLogDTO>? listaFlux { get; set; } = null;
private int MaxRec
{
get => SelFilter.MaxRecord;
}
private int MaxRecord
{
get => SelFilter.MaxRecord;
@@ -387,10 +381,6 @@ namespace MP.SPEC.Components
{
get => SelFilter.IdxMacchina;
}
private int MaxRec
{
get => SelFilter.MaxRecord;
}
private int totalCount
{
+2 -2
View File
@@ -384,7 +384,7 @@ namespace MP.SPEC.Components
private async Task ReloadDataAsync()
{
isLoading = true;
SearchRecords = await MDService.OdlListGetFilt(currFilter.IsActive, currFilter.SearchVal, currFilter.CodFase, currFilter.CodReparto, currFilter.IdxMacchina, currFilter.DtStart, currFilter.DtEnd);
SearchRecords = await MDService.OdlListGetFiltAsync(currFilter.IsActive, currFilter.SearchVal, currFilter.CodFase, currFilter.CodReparto, currFilter.IdxMacchina, currFilter.DtStart, currFilter.DtEnd);
await ReloadPOdlData();
await ReloadLutData();
totalCount = SearchRecords.Count;
@@ -399,7 +399,7 @@ namespace MP.SPEC.Components
if (SearchRecords != null)
{
var listIdx = SearchRecords.Select(x => x.IdxOdl).ToList();
_podlLocalCache = await MDService.PODL_getDictOdlPodl(listIdx);
_podlLocalCache = await MDService.PODL_getDictOdlPodlAsync(listIdx);
#if false
// 1. Popolo la cache locale in parallelo sfruttando la velocità di FusionCache
var tasks = SearchRecords.Select(async odl =>
+31 -13
View File
@@ -6,29 +6,30 @@ namespace MP.SPEC.Components
{
public partial class SelArticolo
{
// Parametri per il Two-Way Data Binding
#region Public Properties
[Parameter]
public string Value { get; set; }
public string SearchVal { get; set; } = "";
[Parameter]
public string SelAzienda { get; set; } = "*";
[Parameter]
public string Value { get; set; } = null!;
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
// Parametri di filtro
[Parameter]
public string SearchVal { get; set; } = "";
[Parameter]
public string SelAzienda { get; set; } = "*";
#endregion Public Properties
#region Protected Properties
[Inject]
protected MpDataService MDService { get; set; } = null!;
private List<AnagArticoliModel>? ListArticoli;
#endregion Protected Properties
// Variabili di appoggio per tracciare il cambio dei filtri
private string _oldSearchVal = string.Empty;
private string _oldSelAzienda = string.Empty;
private int maxNum = 100;
#region Protected Methods
protected override async Task OnInitializedAsync()
{
@@ -46,6 +47,21 @@ namespace MP.SPEC.Components
}
}
#endregion Protected Methods
#region Private Fields
// Variabili di appoggio per tracciare il cambio dei filtri
private string _oldSearchVal = string.Empty;
private string _oldSelAzienda = string.Empty;
private List<AnagArticoliModel>? ListArticoli;
private int maxNum = 100;
#endregion Private Fields
#region Private Methods
private async Task CaricaArticoli()
{
ListArticoli = await MDService.ArticoliGetSearchAsync(maxNum, "*", SelAzienda, SearchVal);
@@ -57,5 +73,7 @@ namespace MP.SPEC.Components
// Notifica il componente padre della variazione
await ValueChanged.InvokeAsync(Value);
}
#endregion Private Methods
}
}
+19 -7
View File
@@ -1726,9 +1726,20 @@ namespace MP.SPEC.Data
/// <param name="startDate">Data inizio</param>
/// <param name="endDate">Data fine</param>
/// <returns></returns>
public async Task<List<ODLExpModel>> OdlListGetFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate)
public async Task<List<ODLExpModel>> OdlListGetFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate)
{
using var activity = ActivitySource.StartActivity("OdlListGetFilt");
string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}";
return await GetOrFetchAsync(
operationName: "OdlListGetFiltAsync",
cacheKey: currKey,
expiration: getRandTOut(redisShortTimeCache),
fetchFunc: async () => await dbController.ListODLFiltAsync(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate) ?? new(),
tagList: [Utils.redisOdlList]
);
#if false
using var activity = ActivitySource.StartActivity("OdlListGetFiltAsync");
List<ODLExpModel>? result = new List<ODLExpModel>();
string source = "DB";
string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}";
@@ -1741,7 +1752,7 @@ namespace MP.SPEC.Data
}
else
{
result = await Task.FromResult(dbController.ListODLFilt(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate));
result = await dbController.ListODLFiltAsync(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate);
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache));
@@ -1753,8 +1764,9 @@ namespace MP.SPEC.Data
activity?.SetTag("data.source", source);
activity?.SetTag("result.count", result.Count);
activity?.Stop();
LogTrace($"OdlListGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms");
return result;
LogTrace($"OdlListGetFiltAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms");
return result;
#endif
}
/// <summary>
@@ -1879,7 +1891,7 @@ namespace MP.SPEC.Data
/// </summary>
/// <param name="idxOdlList"></param>
/// <returns></returns>
public async Task<Dictionary<int, int>> PODL_getDictOdlPodl(List<int> idxOdlList)
public async Task<Dictionary<int, int>> PODL_getDictOdlPodlAsync(List<int> idxOdlList)
{
if (idxOdlList == null || !idxOdlList.Any())
return new Dictionary<int, int>();
@@ -1910,7 +1922,7 @@ namespace MP.SPEC.Data
if (missingIds.Any())
{
// Riceviamo direttamente un Dictionary<int, int> ottimizzato da EF Core
Dictionary<int, int> dbResults = await dbController.PODL_getDictOdlPodl(missingIds);
Dictionary<int, int> dbResults = await dbController.PODL_getDictOdlPodlAsync(missingIds);
// STEP 3: Scriviamo i risultati in cache e li uniamo al dizionario finale
foreach (var kvp in dbResults)
+2 -2
View File
@@ -16,11 +16,11 @@
<span class="input-group-text"><i class="fa fa-search"></i></span>
@if (ShowDetail)
{
<input type="text" class="form-control disabled" disabled placeholder="Search Ctr-R" @bind="@SearchVal" accesskey="R">
<input type="text" class="form-control disabled" disabled placeholder="Search Ctr-R" @bind="@SearchVal" @bind:after="ReloadDataAsync" accesskey="R">
}
else
{
<input type="text" class="form-control" placeholder="Search Ctr-R" @bind="@SearchVal" accesskey="R">
<input type="text" class="form-control" placeholder="Search Ctr-R" @bind="@SearchVal" @bind:after="ReloadDataAsync" accesskey="R">
}
<button class="btn @btnSearchCss" @onclick="ResetSearch"><i class="fa fa-ban"></i></button>
</div>
+5 -6
View File
@@ -30,7 +30,6 @@ namespace MP.SPEC.Pages
if (searchVal != value)
{
searchVal = value;
ReloadDataAsync();
}
}
}
@@ -38,10 +37,10 @@ namespace MP.SPEC.Pages
#endregion Protected Properties
#region Protected Methods
protected override void OnInitialized()
protected override async Task OnInitializedAsync()
{
ReloadDataAsync();
await ReloadBaseDataAsync();
await ReloadDataAsync();
}
#endregion Protected Methods
@@ -77,13 +76,13 @@ namespace MP.SPEC.Pages
#region Private Methods
private void ForceReload(bool doForce)
private async Task ForceReload(bool doForce)
{
if (doForce)
{
CodGruppo = "";
}
ReloadDataAsync();
await ReloadDataAsync();
}
private async Task ReloadBaseDataAsync()