Un modo per velocizzare le nostre applicazioni è aggiungere un livello di memorizzazione nella cache accanto al nostro database. Spesso scriviamo metodi di supporto per leggere i dati dal nostro database, serializzarli e archiviarli nella nostra cache. NCache si integra con Entity Framework Core per memorizzare nella cache le nostre entità con poche righe di codice. Vediamo come implementare una strategia cache-aside con NCache ed Entity Framework Core.
Entity Framework Core non dispone di un meccanismo di memorizzazione nella cache integrato. Dobbiamo fare il nostro. Ma, NCache ha una serie di comodi metodi di estensione per memorizzare facilmente nella cache i risultati delle nostre query.
Con questa integrazione, sfruttiamo tutte le funzionalità di scalabilità e replica di NCache nelle nostre applicazioni Entity Framework.
Creiamo un ASP di esempio.NET Core Applicazione 6.0 per memorizzare nella cache una query Entity Framework Core per mostrare i 10 film più votati in un catalogo.
Come registrarsi NCache con Entity Framework Core
Prima di iniziare, assicuriamoci di averlo NCache installato. Abbiamo bisogno di un'edizione Enterprise o Professional.
Dopo aver creato un ASP.NET Core Applicazione API Web, installiamo EntityFrameworkCore.NCache Pacchetto NuGet. Se utilizziamo un'edizione Professional, installiamo EntityFrameworkCore.NCachePacchetto NuGet .Professional invece.
Registrare NCache con Entity Framework, nel file Program.cs della nostra applicazione, scriviamo,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using Alachisoft.NCache.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(options => { var config = builder.Configuration; var connectionString = config.GetConnectionString("Default"); // Configure NCache with Entity Framework // We need a cacheId and database type NCacheConfiguration.Configure(cacheId: "demoCache", DependencyType.SqlServer); NCacheConfiguration.ConfigureLogger(); options.UseSqlServer(connectionString); }); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run(); |
Sembra un normale ASP.NET Core applicazione che utilizza Entity Framework Core, ad eccezione di due metodi: Configure() e ConfigureLogger() from NCacheConfigurazione.
Con il metodo Configure() specifichiamo il cacheId e il tipo di database. Utilizziamo demoCache, l'istanza della cache predefinita e DependencyType.SqlServer. Ovviamente dovremmo leggere il cacheId da un file di configurazione.
In questo esempio utilizziamo solo un cacheId e un tipo di database, ma possiamo anche passare opzioni di configurazione aggiuntive come tentativi e timeout.
E ConfigureLogger() configura l'astrazione di registrazione sottostante da ASP.NET Core.
Come inserire e memorizzare nella cache i risultati di Entity Framework Core NCache
Dopo la registrazione NCache in Entity Framework Core, stiamo leggendo per iniziare a memorizzare nella cache i nostri film.
Caching dei risultati di Entity Framework Core
Creiamo una classe MoviesController per leggere i 10 migliori film e memorizzarli nella cache NCache. Come questo,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using Alachisoft.NCache.EntityFrameworkCore; using Microsoft.AspNetCore.Mvc; namespace Movies.Controllers; [ApiController] [Route("[controller]")] public class MoviesController : ControllerBase { private readonly DatabaseContext _database; public MoviesController(DatabaseContext database) { _database = database; } [HttpGet] public async Task<IEnumerable> Get() { return await _database .Movies .OrderByDescending(m => m.Rating) .ThenBy(m => m.ReleaseYear) .Take(10) .FromCacheAsync(new CachingOptions { StoreAs = StoreAs.Collection }); } } |
NCache introduce nuovi metodi di estensione oltre ai metodi Entity Framework Core esistenti.
Dopo una query LINQ per recuperare 10 film ordinati per classificazione e anno di uscita, aggiungiamo un nuovo metodo: FromCacheAsync().
FromCacheAsync()
memorizza nella cache il risultato della nostra query LINQ e lo restituisce. Se la nostra cache non ha questo risultato, va al database e poi la memorizza nella cache. Se non riusciamo a connetterci al nostro server cache, NCache restituirà il risultato dal nostro database. Quindi continuerà a riprovare a popolare la cache con il nostro risultato.
Quando si utilizza FromCacheAsync(), passiamo un parametro CachingOptions, dicendo NCache per memorizzare nella cache il risultato della nostra query nel suo complesso anziché voci separate. Ci sono più opzioni per specificare scadenze e priorità.
FromCacheAsyn() dispone di un'alternativa sincrona FromCache()
. A differenza della versione asincrona, FromCache() restituisce la chiave di cache del nuovo elemento come parametro di output.
LoadIntoCache e FromCacheOnly
A parte FromCache() e FromCacheAsync(), NCache ha altri due metodi: LoadIntoCache() e FromCacheOnly().
LoadIntoCache() sovrascrive i risultati memorizzati nella cache a ogni chiamata. Funziona come FromCache() con un errore nella cache ad ogni chiamata. Questo metodo è più adatto per dati modificati di frequente e scenari in cui abbiamo sempre bisogno di una nuova copia dei nostri dati.
FromCacheOnly() non chiama il database sottostante. Va sempre al server cache. FromCacheOnly() supporta funzioni di aggregazione come Sum, Min e Max. Ma lo ha anche fatto alcune limitazioni. Ad esempio, FromCacheOnly() non supporta più proiezioni o join nell'espressione LINQ.
Naturalmente, anche questi ultimi due metodi hanno alternative asincrone.
Inserimento di elementi
Dopo aver memorizzato nella cache i risultati delle nostre query LINQ, vediamo come inserire gli elementi.
Nel MoviesController
class, scriviamo un nuovo metodo per aggiungere un film. Come questo,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// In the same MoviesController.cs file [HttpPost] public async Task Post([FromBody] AddMovie request) { var newMovie = new Movie( name: request.Name, releaseYear: request.ReleaseYear, rating: request.Rating); _database.Movies.Add(newMovie); await _database.SaveChangesAsync(); var options = new CachingOptions { StoreAs = StoreAs.SeperateEntities }; Cache cache = _database.GetCache(); cache.Insert(newMovie, out _, options); } |
Dopo aver inserito un film come facciamo normalmente con SaveChangesAsync(), otteniamo un riferimento alla nostra cache con GetCache(). Quindi, utilizzando lo stesso riferimento all'oggetto, inseriamo un nuovo film con Insert() passando CachingOptions. Possiamo anche passare una priorità, un identificatore di query e tempi di scadenza.
Quando utilizziamo Insert() se la cache contiene già un elemento, questo viene invece aggiornato.
Nota che abbiamo inserito il nuovo elemento nella nostra cache subito dopo aver chiamato SaveChangesAsync(), senza andare nuovamente al database per recuperarlo e quindi memorizzarlo nella cache. Ciò consente di risparmiare un viaggio di andata e ritorno nel nostro database per ogni oggetto che vogliamo inserire.
Conclusione
Ecco come possiamo usare NCache nelle nostre applicazioni Entity Framework Core. Possiamo iniziare a memorizzare nella cache le nostre entità con alcune modifiche alle nostre query LINQ esistenti. Dobbiamo solo estendere la nostra configurazione di Entity Framework
e utilizzare FromCache() e le sue alternative. In questo post abbiamo memorizzato nella cache e inserito elementi, ma possiamo anche farlo rimuovere elementi dalla nostra cache tramite un nome di chiave, un identificatore di query o un riferimento a un oggetto.
Ricordiamo che per query LINQ complesse utilizziamo FromCache(). Per i dati aggiornati di frequente, utilizziamo LoadIntoCache(). E per i dati di sola lettura, FromCacheOnly().
A parte la strategia Cache-aside che abbiamo seguito in questo post, NCache supporta altre strategie e modelli di memorizzazione nella cache come Read-Through e Write-Through. E si integra con l'ASP.NET Core framework per supportare la memorizzazione nella cache dello stato della sessione.
Per seguire il codice che abbiamo scritto in questo post, controlla il mio NCache Deposito dimostrativo su GitHub.