Aggiunto metodo x fornire elenco rel critical attive...

This commit is contained in:
Samuele Locatelli
2024-09-26 19:35:43 +02:00
parent 2e61d79eed
commit 43f69f83de
5 changed files with 292 additions and 202 deletions
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<History>True|2024-09-26T09:41:57.7840547Z||;True|2024-09-26T11:04:11.1945474+02:00||;True|2024-09-26T10:59:21.6944321+02:00||;True|2024-09-26T08:47:21.6588993+02:00||;True|2024-09-24T16:54:23.4735539+02:00||;True|2024-09-24T16:39:32.2152525+02:00||;True|2024-09-24T15:16:02.4976236+02:00||;True|2024-09-24T15:06:15.3728331+02:00||;</History>
<History>True|2024-09-26T13:24:10.3619492Z||;True|2024-09-26T11:41:57.7840547+02:00||;True|2024-09-26T11:04:11.1945474+02:00||;True|2024-09-26T10:59:21.6944321+02:00||;True|2024-09-26T08:47:21.6588993+02:00||;True|2024-09-24T16:54:23.4735539+02:00||;True|2024-09-24T16:39:32.2152525+02:00||;True|2024-09-24T15:16:02.4976236+02:00||;True|2024-09-24T15:06:15.3728331+02:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>
File diff suppressed because one or more lines are too long
+26 -9
View File
@@ -44,6 +44,7 @@ namespace LiMan.APi.Controllers
/// <param name="id">Codice Applicazione</param>
/// <returns></returns>
[HttpGet("{id}")]
[Obsolete("Please use POST with api/release/getall instead.", false)]
public async Task<List<ReleaseDTO>> Get(string id)
{
var result = await dataService.ReleaseGetByApp(id);
@@ -52,12 +53,13 @@ namespace LiMan.APi.Controllers
}
/// <summary>
/// Recupera elenco dati Release (rilasciate) data versione minima GET api/release/EgtBW
/// Recupera elenco dati Release (rilasciate) data versione minima GET api/release/filt/EgtBW
/// </summary>
/// <param name="id">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta (attuale)</param>
/// <returns></returns>
[HttpGet("filt/{id}")]
[Obsolete("Please use POST with api/release/getfilt instead.", false)]
public async Task<List<ReleaseDTO>> GetFilt(string id, string VersMin)
{
var result = await dataService.ReleaseGetByAppVers(id, VersMin);
@@ -66,14 +68,14 @@ namespace LiMan.APi.Controllers
}
/// <summary>
/// Recupera elenco dati Release (rilasciate) data versione minima e massima
/// GET api/release/EgtBW
/// Recupera elenco dati Release (rilasciate) data versione minima e massima GET api/release/filtLimit/EgtBW
/// </summary>
/// <param name="id">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta (attuale)</param>
/// <param name="VersMax">Versione massima consentita</param>
/// <returns></returns>
[HttpGet("filtLimit/{id}")]
[Obsolete("Please use POST with api/release/getlimit instead.", false)]
public async Task<List<ReleaseDTO>> GetFiltLimit(string id, string VersMin, string VersMax)
{
var result = await dataService.ReleaseGetByAppVersLimit(id, VersMin, VersMax);
@@ -82,8 +84,7 @@ namespace LiMan.APi.Controllers
}
/// <summary>
/// Recupera elenco dati Release (rilasciate)
/// POST api/release/getall
/// Recupera elenco dati Release (rilasciate) POST api/release/getall
/// </summary>
/// <param name="CurrRequest">Obj ReleaseReqDTO con chiavi (master o app)</param>
[HttpPost("getall")]
@@ -100,8 +101,25 @@ namespace LiMan.APi.Controllers
}
/// <summary>
/// Recupera elenco dati Release (rilasciate) data versione minima
/// POST api/release/getfilt
/// Recupera elenco dati Release CRITICHE rilasciate (se sono ultima per singola CodApp)
/// POST api/release/get-critical
/// </summary>
/// <param name="CurrRequest">Obj ReleaseReqDTO con chiavi (master o app)</param>
[HttpPost("getcritical")]
public async Task<Dictionary<string, ReleaseDTO>> GetReleasesCritical([FromBody] ReleaseReqDTO CurrRequest)
{
Dictionary<string, ReleaseDTO> result = new Dictionary<string, ReleaseDTO>();
// verifica validità richiesta...
if (CheckReqKeys(CurrRequest))
{
result = await dataService.ReleaseGetCritical();
await dataService.recordCall(CurrRequest.CodApp, CurrRequest.CodApp, $"POST:api/release/getcritical/ | {CurrRequest.MastKey} | {CurrRequest.CodImp} | {CurrRequest.CodApp}");
}
return result;
}
/// <summary>
/// Recupera elenco dati Release (rilasciate) data versione minima POST api/release/getfilt
/// </summary>
/// <param name="CurrRequest">Obj ReleaseReqDTO con chiavi (master o app)</param>
[HttpPost("getfilt")]
@@ -118,8 +136,7 @@ namespace LiMan.APi.Controllers
}
/// <summary>
/// Recupera elenco dati Release (rilasciate) data versione minima e massima
/// POST api/release/getlimit
/// Recupera elenco dati Release (rilasciate) data versione minima e massima POST api/release/getlimit
/// </summary>
/// <param name="CurrRequest">Obj ReleaseReqDTO con chiavi (master o app)</param>
[HttpPost("getlimit")]
+218 -188
View File
@@ -34,17 +34,6 @@ namespace LiMan.APi.Data
#endregion Public Fields
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
protected IConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
protected IDatabase redisDb = null!;
protected static JsonSerializerSettings? JSSettings;
#region Public Constructors
/// <summary>
@@ -89,6 +78,20 @@ namespace LiMan.APi.Data
#region Public Methods
/// <summary> Elenco Applicativi (all) <returns></returns>
public async Task<List<ApplicativoModel>> ApplicativiGetAll()
{
List<ApplicativoModel> dbResult = new List<ApplicativoModel>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.GetApplicazioni();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ApplicativiGetAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
/// <summary>
/// Elenco licenze dato cliente
/// </summary>
@@ -109,21 +112,6 @@ namespace LiMan.APi.Data
return await Task.FromResult(dbResult);
}
/// <summary>
/// Elenco Applicativi (all)
/// <returns></returns>
public async Task<List<ApplicativoModel>> ApplicativiGetAll()
{
List<ApplicativoModel> dbResult = new List<ApplicativoModel>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.GetApplicazioni();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ApplicativiGetAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
/// <summary>
/// Aggiornameto/Inserimento record applicativo
/// </summary>
@@ -142,126 +130,6 @@ namespace LiMan.APi.Data
Log.Trace($"Effettuato upsert su DB per ApplicativoUpsert | {newRec.CodApp} | {ts.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Aggiornameto/Inserimento record release
/// </summary>
/// <param name="newRec">record Release</param>
/// <returns></returns>
public async Task<bool> ReleaseUpsert(ReleaseModel newRec)
{
await Task.Delay(1);
bool fatto = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// inserisco
fatto = await dbController.ReleaseUpsert(newRec);
await InvalidateAllCache();
await FlushRedisCache();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuato upsert su DB per ReleaseUpsert | {newRec.CodApp} | {newRec.VersNum} | {ts.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Refresh globale cache redis
/// </summary>
/// <returns></returns>
public async Task<bool> FlushRedisCache()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
await Task.Delay(1);
RedisValue pattern = new RedisValue($"{Const.rKeyConfig}:*");
bool answ = await ExecFlushRedisPattern(pattern);
stopWatch.Stop();
Log.Debug($"FlushRedisCache in {stopWatch.Elapsed.TotalMilliseconds} ms");
return answ;
}
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
protected async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
{
bool answ = false;
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
var server = redisConn.GetServer(endPoint);
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
answ = true;
}
}
return answ;
}
/// <summary>
/// Elenco Release dato Applicativo
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByApp(string CodApp)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByApp(CodApp);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByApp | {CodApp} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco Release dato Applicativo + versione minima
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByAppVers(string CodApp, string VersMin)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByAppVers(CodApp, VersMin);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVers | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco Release dato Applicativo + versione minima
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta</param>
/// <param name="VersMax">Versione massima consentita</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByAppVersLimit(string CodApp, string VersMin, string VersMax)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByAppVersLimit(CodApp, VersMin, VersMax);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVersLimit | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco licenze dato cliente
@@ -487,6 +355,22 @@ namespace LiMan.APi.Data
return await Task.FromResult(dbResult);
}
/// <summary>
/// Refresh globale cache redis
/// </summary>
/// <returns></returns>
public async Task<bool> FlushRedisCache()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
await Task.Delay(1);
RedisValue pattern = new RedisValue($"{Const.rKeyConfig}:*");
bool answ = await ExecFlushRedisPattern(pattern);
stopWatch.Stop();
Log.Debug($"FlushRedisCache in {stopWatch.Elapsed.TotalMilliseconds} ms");
return answ;
}
/// <summary>
/// invalida tutta la cache in caso di update
/// </summary>
@@ -533,48 +417,6 @@ namespace LiMan.APi.Data
return await Task.FromResult(dbResult);
}
/// <summary>
/// Statistiche del LOG chiamate all'API dato filtro
/// </summary>
/// <param name="DateFrom">Data minima</param>
/// <param name="DateTo">DataMax</param>
/// <param name="SearchVal">Valore cercato, se "" è tutti</param>
/// <returns></returns>
public async Task<List<StatsCallModel>> StatsLogCallGetFilt(DateTime DateFrom, DateTime DateTo, string SearchVal = "")
{
List<StatsCallModel> dbResult = new List<StatsCallModel>();
string cacheKey = $"{rKeyStatslogCall}:{DateFrom:yyyyMMdd}:{DateTo:yyyyMMdd}";
if(!string.IsNullOrEmpty(SearchVal))
{
cacheKey += $":{SearchVal}";
}
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<List<StatsCallModel>>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var rawResult = dbController.StatsLogCallGetFilt(DateFrom, DateTo, SearchVal);
dbResult = rawResult
.OrderByDescending(x => x.YearRef)
.ThenByDescending(x => x.TotCall)
.ToList();
if (dbResult != null)
{
rawData = JsonConvert.SerializeObject(dbResult);
await setRSV(cacheKey, rawData, shortTTL);
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per StatsLogCallGetFilt: {ts.TotalMilliseconds} ms");
}
return await Task.FromResult(dbResult);
}
/// <summary>
/// Effettua refresh del payload della licenza dato info + enigma generato dal client
/// </summary>
@@ -693,6 +535,113 @@ namespace LiMan.APi.Data
return fatto;
}
/// <summary>
/// Elenco Release dato Applicativo
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByApp(string CodApp)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByApp(CodApp);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByApp | {CodApp} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco Release dato Applicativo + versione minima
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByAppVers(string CodApp, string VersMin)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByAppVers(CodApp, VersMin);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVers | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco Release dato Applicativo + versione minima
/// </summary>
/// <param name="CodApp">Codice Applicazione</param>
/// <param name="VersMin">Versione minima richiesta</param>
/// <param name="VersMax">Versione massima consentita</param>
/// <returns></returns>
public async Task<List<ReleaseDTO>> ReleaseGetByAppVersLimit(string CodApp, string VersMin, string VersMax)
{
await Task.Delay(1);
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.ReleaseDtoGetByAppVersLimit(CodApp, VersMin, VersMax);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVersLimit | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Elenco di TUTTE le release CRITICAL come dizionario CodApp - release
/// </summary>
/// <returns></returns>
public async Task<Dictionary<string, ReleaseDTO>> ReleaseGetCritical()
{
Dictionary<string, ReleaseDTO> dbResult = new Dictionary<string, ReleaseDTO>();
Stopwatch sw = new Stopwatch();
sw.Start();
string cacheKey = $"{rKeyAttivByLic}:AppReleases:CRITICAL";
string source = "REDIS";
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<Dictionary<string, ReleaseDTO>>(rawData);
}
else
{
source = "DB";
dbResult = dbController.ReleaseGetCritical();
rawData = JsonConvert.SerializeObject(dbResult);
await setRSV(cacheKey, rawData, shortTTL);
}
sw.Stop();
Log.Trace($"Effettuata lettura da DB per ReleaseGetCritical | {source} | # found: {dbResult.Count} | {sw.ElapsedMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Aggiornameto/Inserimento record release
/// </summary>
/// <param name="newRec">record Release</param>
/// <returns></returns>
public async Task<bool> ReleaseUpsert(ReleaseModel newRec)
{
await Task.Delay(1);
bool fatto = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// inserisco
fatto = await dbController.ReleaseUpsert(newRec);
await InvalidateAllCache();
await FlushRedisCache();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuato upsert su DB per ReleaseUpsert | {newRec.CodApp} | {newRec.VersNum} | {ts.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Registro su DB le statistiche delle chiavi in elenco, resettando i vari contatori quando fatto
/// </summary>
@@ -748,6 +697,48 @@ namespace LiMan.APi.Data
return answ;
}
/// <summary>
/// Statistiche del LOG chiamate all'API dato filtro
/// </summary>
/// <param name="DateFrom">Data minima</param>
/// <param name="DateTo">DataMax</param>
/// <param name="SearchVal">Valore cercato, se "" è tutti</param>
/// <returns></returns>
public async Task<List<StatsCallModel>> StatsLogCallGetFilt(DateTime DateFrom, DateTime DateTo, string SearchVal = "")
{
List<StatsCallModel> dbResult = new List<StatsCallModel>();
string cacheKey = $"{rKeyStatslogCall}:{DateFrom:yyyyMMdd}:{DateTo:yyyyMMdd}";
if (!string.IsNullOrEmpty(SearchVal))
{
cacheKey += $":{SearchVal}";
}
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<List<StatsCallModel>>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var rawResult = dbController.StatsLogCallGetFilt(DateFrom, DateTo, SearchVal);
dbResult = rawResult
.OrderByDescending(x => x.YearRef)
.ThenByDescending(x => x.TotCall)
.ToList();
if (dbResult != null)
{
rawData = JsonConvert.SerializeObject(dbResult);
await setRSV(cacheKey, rawData, shortTTL);
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per StatsLogCallGetFilt: {ts.TotalMilliseconds} ms");
}
return await Task.FromResult(dbResult);
}
/// <summary>
/// Esegue aggiunta Ticket richiesto + restitusice aperti x cliente
/// </summary>
@@ -851,10 +842,49 @@ namespace LiMan.APi.Data
/// </summary>
protected const int shortTTL = 60 * 5;
protected static JsonSerializerSettings? JSSettings;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
protected IConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
protected IDatabase redisDb = null!;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
protected async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
{
bool answ = false;
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
var server = redisConn.GetServer(endPoint);
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
answ = true;
}
}
return answ;
}
/// <summary>
/// Recupera statistiche correnti
/// </summary>
+46 -3
View File
@@ -72,6 +72,7 @@ namespace LiMan.DB.Controllers
}
return fatto;
}
/// <summary>
/// Verifica se una applcazione abbia record correlati...
/// </summary>
@@ -348,7 +349,8 @@ namespace LiMan.DB.Controllers
{
try
{
// cerco eventuali licenze preesistenti (per CodImp) e le elimino SE sono libere...
// cerco eventuali licenze preesistenti (per CodImp) e le elimino SE
// sono libere...
List<SubLicenzaModel> list2rem = new List<SubLicenzaModel>();
foreach (var item in ParamDict)
{
@@ -356,13 +358,13 @@ namespace LiMan.DB.Controllers
.DbSetSubLicenze
.Where(x => x.CodImpiego == item.Key && x.VetoUnlock <= oggi)
.FirstOrDefault();
if(rec2del!=null)
if (rec2del != null)
{
list2rem.Add(rec2del);
}
}
// se ce ne sono rimuovo e salvo...
if(list2rem!=null && list2rem.Count>0)
if (list2rem != null && list2rem.Count > 0)
{
dbCtx
.DbSetSubLicenze
@@ -1510,6 +1512,47 @@ namespace LiMan.DB.Controllers
return dbResult;
}
/// <summary>
/// Elenco di TUTTE le release CRITICAL come dizionario CodApp - release
/// </summary>
/// <param name="CodApp">Codice applicativo</param>
/// <returns></returns>
public Dictionary<string, ReleaseDTO> ReleaseGetCritical()
{
Dictionary<string, ReleaseDTO> dbResult = new Dictionary<string, ReleaseDTO>();
using (LMDbContext localDbCtx = new LMDbContext(_configuration))
{
DateTime adesso = DateTime.Now;
// primo step: seleziono le ULTIME release x ogni app...
var rawList = localDbCtx
.DbSetReleases
.Where(x => x.ReleaseDate <= adesso)
//.OrderByDescending(x => x.VersNum)
.GroupBy(x => x.CodApp)
.Select(g => new
{
key = g.Key,
val = g.Where(x => x.ReleaseDate <= adesso).OrderByDescending(x => x.VersNum).FirstOrDefault()
})
.ToList();
foreach (var item in rawList)
{
if (!dbResult.ContainsKey(item.key) && item.val.RelTags == "CRITICAL")
{
dbResult.Add(item.key, new ReleaseDTO()
{
CodApp = item.val.CodApp,
ReleaseDate = item.val.ReleaseDate,
VersNum = item.val.VersNum,
VersText = item.val.VersText,
VersVal = item.val.VersVal
});
}
}
}
return dbResult;
}
/// <summary>
/// Upsert Record Release
/// </summary>