Sto cercando un sistema di cache che funzioni con Entity Framework 6+. O per trovare una libreria adatta o implementarla da solo.
Ho già studiato questi due provider di cache open source:
Secondo livello di cache per Entity Framework 6.1 https://efcache.codeplex.com/
EFSecondLevelCache https://github.com/VahidN/EFSecondLevelCache/
Sembrano prodotti solidi, anche se sto cercando un modo per specificare il tempo massimo di cache all'interno della query. Penso che sarebbe il modo migliore per specificare i dati più vecchi che sarei in grado di accettare (poiché questo dipende molto dalla logica di business, ovviamente)
Questo sarebbe il modo migliore per chiamarlo penso:
using (var db = new MyEF6Entities()) {
var path = db.Configuration.Where(c => c.name="Path")
.AllowFromCache(TimeSpan.FromMinutes(60));
var onlineUserList = db.Users.Where(u => u.IsOnline)
.AllowFromCache(TimeSpan.FromSeconds(30));
}
C'è un modo per creare un'API come questa?
EDIT: ora ho provato EF + come suggerito da @JonathanMagnan ma ad esempio il codice qui sotto non ottiene mai un colpo di cache. Lo so perché è molto lento, vedo anche nell'amministratore mysql che c'è una connessione fatta con la query specifica, e se cambio i dati nel database che mostrerà immediatamente, mi aspetterei un ritardo di 60 minuti
public String GetClientConfig(string host, Guid deviceId) {
using (var db = new DbEntities(host)) {
var clientConfig = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60)).ToList();
return string.Join("\n", clientConfig.Select(b => b.Name + "=" + b.Value));
}
return null;
}
EDIT 2: mi sono reso conto che la memorizzazione nella cache non funziona, ma crea comunque una connessione al database perché creo una nuova istanza di contesto. C'è comunque un problema! Faccio richieste EF in un servizio web. A seconda del nome host del servizio web Host: vengono interrogati diversi database. EF Plus non sembra gestirlo, quindi se utilizzo http: // host1 / ClientConfig, in seguito ottengo gli stessi risultati non corretti da http: // host2 / ClientConfig . C'è un modo per taggare la cache con il nome host?
Disclaimer : sono il proprietario del progetto Entity Framework Plus (EF +)
Non riesco a parlare per altre librerie che hai già studiato, ma EF + Query Cache consente di memorizzare nella cache i dati per un determinato periodo di tempo.
Wiki: EF + Query Cache
Esempio
using (var db = new MyEF6Entities()) {
var path = db.Configuration.Where(c => c.name="Path")
.FromCache(DateTime.Now.AddMinutes(60));
var onlineUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddSeconds(30));
}
È anche possibile utilizzare i "tag" della cache per memorizzare i dati in cache più volte se una logica richiede dati in tempo reale e non è necessario che l'altra logica ne abbia bisogno.
Esempio
using (var db = new MyEF6Entities()) {
var recentUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddHours(1), "recent");
var onlineUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddSeconds(30), "online");
}
Da quanto ne so, non penso che nessun supporto per la cache stia prendendo i dati nella cache negli ultimi X secondi.
MODIFICA : rispondi sottoquestion
Grazie Jonathan. Come funziona EF + con l'utilizzo di diversi database, ad esempio, e diversi utenti registrati, ad esempio. Gestirà questo automaticamente o devo dargli qualche suggerimento?
Dipende da ciascuna caratteristica. Ad esempio, Query Cache funziona con tutti i provider di database poiché solo LINQ viene utilizzato sotto il cofano. Non è necessario specificare nulla, già gestisce tutto.
Alcune altre funzionalità come Query Future non funzionano ancora su tutti i provider. Funziona su provider famosi come SQL Server, SQL Azure e MySQL.
Puoi vedere la sezione dei requisiti sotto ogni funzione. Diciamo normalmente "Tutti supportati" se supporta tutti i provider.
MODIFICA : rispondi sottoquestion
Cambio il database nel costruttore MyEF6Entities, quindi la domanda è se EF + prenderà in considerazione il nome del database o se questo potrebbe rovinare la cache?
A partire dalla v1.3.34, la stringa di connessione è ora parte della chiave. Questo supporterà questo scenario.
La chiave è composta da:
C'è un modo per taggare la cache con il nome host
Puoi utilizzare i tag della cache: EF + Query Cache Tag e ExpireTag
Esempio:
var host1 = "http://host1/ClientConfig";
var host2 = "http://host2/ClientConfig";
var clientHost1 = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60), host1).ToList();
var clientHost1 = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60), host2).ToList();
Tutti i tag fanno parte della chiave di cache, quindi entrambe le query verranno memorizzate nella cache in una voce di cache diversa.
MODIFICA : rispondi sottoquestion
Ho impostato ConnectionString nel costruttore MyEF6Entities () e sembra ancora confondere i dati da diversi database
Puoi generare la chiave di cache e controllare se la stringa di connessione è inclusa?
var query = b.Users.Where(u => u.IsOnline);
var cacheKey = QueryCacheManager.GetCacheKey(query, new string[0]);
Funziona se faccio per esempio var clientHost = db.ClientConfig.FromCache (DateTime.Now.AddMinutes (60), hostName) .ToList (); ma non dovrei aver bisogno di questo perché le stringhe di connessione sono diverse, giusto?
Si hai ragione. Non dovrebbe essere necessario se la stringa di connessione cambia con l'host.