110 messaggi dal 26 febbraio 2007
Ciao,

Sto utilizzando la MemoryCache per salvare alcuni dati letti da un file.

nello startup ho inserito services.AddMemoryCache(); e con il metodo _memoryCache.GetOrCreate vado a leggere (o la prima volta a setatre la cache).


Ho notato che se faccio una modifica all'oggetto che ho ottenuto dalla cache, questo viene subito modificato anche in cache, e se un'altro utente dovesse richiedere l'oggetto dalla cache, si troverà subito la modifica fatta da un'altro utente.

Cercando in rete mi sembra di aver capito che la memorycache crea un singleton, quindi in pratica ho una variaibile condivisa tra tutti gli utenti? è per questo che l'utente si trova subito le modifiche fatti da altri?

Io mi aspettavo che per far vedere la modifica anche agli altri utenti dovessi aver fatto prima una nuova Set del valore in cache. Non c'è modo di ottenere questo comportamento? altrimenti sono costretto ad eliminare il dato dalla cache
11.511 messaggi dal 09 febbraio 2002
Contributi

che la memorycache crea un singleton, quindi in pratica ho una variaibile condivisa tra tutti gli utenti

Esatto, è un servizio col ciclo di vita singleton e perciò ogni utente potrà accedere ai valori impostati da un altro utente. Questo è comodo, ad esempio, per evitare chiamate al database per dati pubblici che cambiano di rado, tipo le categorie di prodotto di un e-commerce.
Puoi usare la cache anche per dati lenti da ottenere, tipo da un webservice di terze parti che ci mette un po' di tempo a rispondere.


Ho notato che se faccio una modifica all'oggetto che ho ottenuto dalla cache, questo viene subito modificato anche in cache

È normale, perché l'oggetto non viene clonato quando lo inserisci in cache o quando lo recuperi. La cache tiene semplicemente un riferimento all'oggetto in memoria, così che non venga rimosso dal garbage collector. Ne consegue che anche l'oggetto stesso è una sorta di singleton e perciò se ne muti lo stato interno devi farlo in maniera thread-safe.

Che devi realizzare, esattamente?

ciao,
Moreno
Modificato da BrightSoul il 01 marzo 2019 19:10 -

Enjoy learning and just keep making
110 messaggi dal 26 febbraio 2007
Devo leggere un file json di config, quindi per evitare di accedere ad ogni richiesta al filesystem, lo avevo messo in cache.

Però durante l'utilizzo degli utenti (sia che abbiano fatto la login, che anonimi), questo oggetto può subire un paio di modifiche ad alcuni valori (che non devono essere salvate, perchè riguardano la singola chiamata).
11.511 messaggi dal 09 febbraio 2002
Contributi
Ciao, ASP.NET Core ha già un sistema di configurazione basato su file JSON (e volendo su altri tipi di fonte). Leggi qui:
https://forum.aspitalia.com/forum/post/420254/Accedere-AppSettings-Classe.aspx

questo oggetto può subire un paio di modifiche ad alcuni valori (che non devono essere salvate, perchè riguardano la singola chiamata).

Come ottieni i valori che ridefiniscono quelli presenti nel json? Dalla richiesta? Dal database?

ciao,
Moreno

Enjoy learning and just keep making
110 messaggi dal 26 febbraio 2007
Alcuni valori dal DB, altri da una chiamata ad un webserver esterno
11.511 messaggi dal 09 febbraio 2002
Contributi
Ok, ti consiglio questa soluzione, valuta tu se è idonea al tuo caso. Servirà un po' di lavoro ma almeno dovrebbe consentirti di risolvere il problema e soprattutto riutilizzerai il servizio di configurazione e la dependency injection di ASP.NET Core.

Per prima cosa creati una classe che avrà lo scopo di recuperare le informazioni di default usando il servizio IConfiguration e il suo metodo Bind(), e poi ci scrivi sopra i valori ottenuti dal database o dall'altro webserver.
Vado a braccio:

public class ConfigurationService : IConfigurationService
{
   private readonly IConfiguration configuration;
   private readonly IHttpContextAccessor accessor;

   public ConfigurationService(IConfiguration configuration, IHttpContextAccessor accessor) {
     this.configuration = configuration;
     this.accessor = accessor;
   }

   public async Task<AppOptions> GetOptions() {

       //Istanzio la mia classe AppOptions che contiene alcune proprietà di configurazione
       //e la riempio con i valori di default
       var options = new AppOptions();
       configuration.Bind("App", options);
       
       //Qui recuperi i valori dal database e poi li scrivi sull'istanza di AppOptions
       //Supponiamo che tu abbia un metodo GetOptionsFromDatabase
       //che restituisce un DataTable con dentro i valori per l'utente corrente...
       var dataTable = await GetOptionsFromDatabase(accessor.HttpContext.User.Identity.Name);
       options.Value1 = dataTable.Rows[0]["Value1"] as string;

       return options;
   }

   private async Task<DataTable> GetOptionsFromDatabase(string userName) {
       //TODO...
   }
}

public class AppOptions
{
    public string Value1 { get; set; }
}

public interface IConfigurationService
{
     Task<AppOptions> GetOptions();
}


Come vedi nel codice, ho creato una nuova istanza di AppOptions(), quindi ogni utente avrà la sua. A questo punto registra questo servizio come transient o come scoped dal metodo ConfigureServices della classe Startup.
services.AddTransient<IConfigurationService, ConfigurationService>();


e adesso ricevi il servizio all'interno dei tuoi componenti, ad esempio nell'action di un controller.
public class HomeController {

  public async Task<IActionResult> Index([FromServices] IConfigurationService confService) {
    AppOptions options = await confService.GetOptions();   
    //TODO: fai qualcosa con options.
  }
}


Ora resta soltanto aprire il file appsettings.json e aggiungere la configurazione di default così:
{
   "App": {
      "Value1": "ABCDEF"
    }
}


ciao,
Moreno
Modificato da BrightSoul il 04 marzo 2019 22:58 -

Enjoy learning and just keep making
110 messaggi dal 26 febbraio 2007
grazie mille, si riadatta perfettamente a quello di cui ho bisogno!

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.