Update pag articoli

- fix ricerca
- fix cache REDIS
- filtro search in pagina(RAM)
This commit is contained in:
Samuele Locatelli
2025-08-09 10:04:46 +02:00
parent dd655c3631
commit cf0d4e2aed
4 changed files with 283 additions and 54 deletions
@@ -10,6 +10,7 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static EgwCoreLib.Lux.Core.Enums;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EgwCoreLib.Lux.Data.Controllers
@@ -124,11 +125,13 @@ namespace EgwCoreLib.Lux.Data.Controllers
}
/// <summary>
/// Elenco item da ricerca
/// Elenco item da ricerca filtro x gruppo/tipo
/// </summary>
/// <param name="term"></param>
/// <param name="SearchVal"></param>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <returns></returns>
public List<ItemModel> ItemGetSearch(string term)
public List<ItemModel> ItemGetFilt(string CodGroup, ItemClassType ItemType)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
@@ -138,7 +141,131 @@ namespace EgwCoreLib.Lux.Data.Controllers
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.Description.Contains(term))
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType))
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca completa
/// </summary>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <param name="SearchVal"></param>
/// <returns></returns>
public List<ItemModel> ItemGetFilt(string CodGroup, ItemClassType ItemType, string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType)
&& (string.IsNullOrEmpty(SearchVal) ||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca filtro x gruppo/tipo Async
/// </summary>
/// <param name="SearchVal"></param>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetFiltAsync(string CodGroup, ItemClassType ItemType)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType))
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFiltAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca completa Async
/// </summary>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <param name="SearchVal"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetFiltAsync(string CodGroup, ItemClassType ItemType, string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType)
&& (string.IsNullOrEmpty(SearchVal) ||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFiltAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca
/// </summary>
/// <param name="SearchVal"></param>
/// <returns></returns>
public List<ItemModel> ItemGetSearch(string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
.ToList();
}
catch (Exception exc)
@@ -152,9 +279,9 @@ namespace EgwCoreLib.Lux.Data.Controllers
/// <summary>
/// Elenco item da ricerca async
/// </summary>
/// <param name="term"></param>
/// <param name="SearchVal"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetSearchAsync(string term)
public async Task<List<ItemModel>> ItemGetSearchAsync(string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
@@ -164,7 +291,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
{
dbResult = await dbCtx
.DbSetItem
.Where(x => x.Description.Contains(term) || string.IsNullOrEmpty(term))
.Where(x => x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
.ToListAsync();
}
catch (Exception exc)
@@ -12,6 +12,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static EgwCoreLib.Lux.Core.Enums;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EgwCoreLib.Lux.Data.Services
@@ -147,40 +148,91 @@ namespace EgwCoreLib.Lux.Data.Services
}
/// <summary>
/// Elenco completo offerte da DB
/// Eliminazione record item
/// </summary>
/// <param name="rec2del"></param>
/// <returns></returns>
public async Task<List<OfferModel>> OfferGetAll()
public async Task<bool> ItemDeleteAsync(ItemModel rec2del)
{
bool result = await dbController.ItemDeleteAsync(rec2del);
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Item:*");
return result;
}
/// <summary>
/// Elenco item da ricerca completa Async
/// </summary>
/// <param name="SearchVal"></param>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetFiltAsync(string SearchVal, string CodGroup, ItemClassType ItemType)
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<OfferModel>? result = new List<OfferModel>();
List<ItemModel>? result = new List<ItemModel>();
// cerco in redis...
string currKey = $"{redisBaseKey}:Offers:ALL";
string searchTok = string.IsNullOrEmpty(SearchVal) ? "ALL" : SearchVal;
string groupTok = string.IsNullOrEmpty(CodGroup) ? "ALL" : CodGroup;
string currKey = $"{redisBaseKey}:Item:Filt:{groupTok}:{ItemType}:{searchTok}";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<OfferModel>>($"{rawData}");
result = JsonConvert.DeserializeObject<List<ItemModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = await dbController.OfferGetAll();
result = await dbController.ItemGetFiltAsync(SearchVal, CodGroup, ItemType);
// serializzo e salvo con config x evitare loop...
rawData = JsonConvert.SerializeObject(result, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<OfferModel>();
result = new List<ItemModel>();
}
sw.Stop();
Log.Debug($"OfferGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms");
Log.Debug($"ItemGetFiltAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Elenco item da ricerca async
/// </summary>
/// <param name="term"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetSearchAsync(string term)
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<ItemModel>? result = new List<ItemModel>();
// cerco in redis...
string token = string.IsNullOrEmpty(term) ? "ALL" : term;
string currKey = $"{redisBaseKey}:Item:Search:{token}";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<ItemModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = await dbController.ItemGetSearchAsync(term);
// serializzo e salvo con config x evitare loop...
rawData = JsonConvert.SerializeObject(result, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<ItemModel>();
}
sw.Stop();
Log.Debug($"ItemGetSearchAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Elenco completo ItemGroup gestiti
@@ -217,50 +269,37 @@ namespace EgwCoreLib.Lux.Data.Services
}
/// <summary>
/// Elenco item da ricerca async
/// Elenco completo offerte da DB
/// </summary>
/// <param name="term"></param>
/// <returns></returns>
public async Task<List<ItemModel>> ItemGetSearchAsync(string term)
public async Task<List<OfferModel>> OfferGetAll()
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<ItemModel>? result = new List<ItemModel>();
List<OfferModel>? result = new List<OfferModel>();
// cerco in redis...
string token = string.IsNullOrEmpty(term) ? "ALL" : term;
string currKey = $"{redisBaseKey}:Item:{token}";
string currKey = $"{redisBaseKey}:Offers:ALL";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<ItemModel>>($"{rawData}");
result = JsonConvert.DeserializeObject<List<OfferModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = await dbController.ItemGetSearchAsync(term);
result = await dbController.OfferGetAll();
// serializzo e salvo con config x evitare loop...
rawData = JsonConvert.SerializeObject(result, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<ItemModel>();
result = new List<OfferModel>();
}
sw.Stop();
Log.Debug($"ItemGetSearchAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Eliminazione record item
/// </summary>
/// <param name="rec2del"></param>
/// <returns></returns>
public async Task<bool> ItemDeleteAsync(ItemModel rec2del)
{
bool result = await dbController.ItemDeleteAsync(rec2del);
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Item:*");
Log.Debug($"OfferGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
+4 -5
View File
@@ -8,7 +8,7 @@
</div>
<div class="px-0 d-flex justify-content-between">
<div class="px-0">
@if (!string.IsNullOrEmpty(SelCodGroup))
@if (!string.IsNullOrEmpty(SelCodGroup) && SelType != Enums.ItemClassType.ND)
{
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-cart-plus"></i> Nuovo</button>
}
@@ -25,7 +25,6 @@
</select>
<span class="input-group-text">Tipo</span>
<select @bind="@SelType" class="form-select">
<option value="">--- Sel. Tipo ---</option>
@foreach (var sType in Enum.GetValues(typeof(EgwCoreLib.Lux.Core.Enums.ItemClassType)))
{
<option value="@sType">@sType</option>
@@ -36,8 +35,8 @@
<div class="px-1">
<div class="input-group input-group-sm" title="ricerca">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<input type="text" class="form-control" @bind="@searchVal">
<button class="btn btn-outline-secondary" @onclick="resetSearch"><i class="fas fa-ban"></i></button>
<input type="text" class="form-control" @bind="@SearchVal">
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
</div>
</div>
</div>
@@ -107,7 +106,7 @@
<button class="btn btn-sm btn-secondary disabled"><i class="fa-solid fa-trash-can"></i></button>
}
</td>
</td>
</tr>
}
+75 -11
View File
@@ -13,11 +13,6 @@ namespace Lux.UI.Components.Pages
protected List<ItemGroupModel> ListItemGroup = new List<ItemGroupModel>();
protected List<ItemModel> ListRecords = new List<ItemModel>();
protected string searchVal = "";
protected string? SelCodGroup = null;
protected EgwCoreLib.Lux.Core.Enums.ItemClassType? SelType = null;
#endregion Protected Fields
#region Protected Properties
@@ -28,6 +23,63 @@ namespace Lux.UI.Components.Pages
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
protected string SearchVal
{
get => searchVal;
set
{
if (searchVal != value)
{
searchVal = value;
currPage = 1;
var pUpd = Task.Run(async () =>
{
await ReloadData();
UpdateTable();
});
pUpd.Wait();
}
}
}
protected string SelCodGroup
{
get => selCodGroup;
set
{
if (selCodGroup != value)
{
selCodGroup = value;
currPage = 1;
var pUpd = Task.Run(async () =>
{
await ReloadData();
UpdateTable();
});
pUpd.Wait();
}
}
}
protected EgwCoreLib.Lux.Core.Enums.ItemClassType SelType
{
get => selType;
set
{
if (selType != value)
{
selType = value;
currPage = 1;
var pUpd = Task.Run(async () =>
{
await ReloadData();
UpdateTable();
});
pUpd.Wait();
}
}
}
#endregion Protected Properties
#region Protected Methods
@@ -59,8 +111,8 @@ namespace Lux.UI.Components.Pages
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.ItemID} | {selRec.CodGroup} | {selRec.ItemType} | {selRec.ExtItemCode}"))
return;
// esegue eliminazione del record...
await DLService.ItemDeleteAsync(selRec);
//// esegue eliminazione del record...
//await DLService.ItemDeleteAsync(selRec);
EditRecord = null;
SelRecord = null;
@@ -91,9 +143,9 @@ namespace Lux.UI.Components.Pages
UpdateTable();
}
protected void resetSearch()
protected void ResetSearch()
{
searchVal = "";
SearchVal = "";
}
protected void SaveNumRec(int newNum)
@@ -113,11 +165,13 @@ namespace Lux.UI.Components.Pages
#region Private Fields
private int currPage = 1;
private ItemModel? EditRecord = null;
private bool isLoading = false;
private int numRecord = 10;
private string searchVal = "";
private string selCodGroup = "";
private ItemModel? SelRecord = null;
private EgwCoreLib.Lux.Core.Enums.ItemClassType selType = EgwCoreLib.Lux.Core.Enums.ItemClassType.ND;
private int totalCount = 0;
#endregion Private Fields
@@ -132,7 +186,17 @@ namespace Lux.UI.Components.Pages
private async Task ReloadData()
{
isLoading = true;
AllRecords = await DLService.ItemGetSearchAsync(searchVal);
AllRecords = await DLService.ItemGetFiltAsync(SelCodGroup, SelType);
// se ho ricerca testuale faccio filtro ulteriore...
if (!string.IsNullOrEmpty(SearchVal))
{
AllRecords = AllRecords
.Where(x =>
x.Description.Contains(searchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.ExtItemCode.Contains(searchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.SupplCode.Contains(searchVal, StringComparison.InvariantCultureIgnoreCase))
.ToList();
}
totalCount = AllRecords.Count;
}