Ho cercato di capire uno scenario in cui questo tipo di approccio potrebbe essere utile senza portare a una memoria ingombrante che è faticosamente difficile da mantenere.
So che questo non è direttamente rispondere alla tua domanda, ma vorrei sollevare alcune domande su questo approccio che, in un primo momento, può sembrare allettante:
- Come hai intenzione di gestire il parametro ordinamento? Vale a dire. (x => x.blah == "slug" & &! x.Cancellato) chiave della cache dovrebbe essere uguale (x =>! X.Deleted & & x.blah == "slug") chiave di cache.
- Come pensavi di evitare gli oggetti duplicati nella cache? Vale a dire. La stessa farm da più query dovrebbe essere memorizzata in cache separatamente per ogni query. Ad esempio, per ogni lumaca visualizzata nella farm, abbiamo una copia separata della farm.
- Estendere quanto sopra con più parametri, come pacchi, agricoltori, ecc. Porterebbe a più query corrispondenti con ciascuna una copia separata della farm memorizzata nella cache. Lo stesso vale per ogni tipo che potresti interrogare più i parametri potrebbero non essere nello stesso ordine
- Ora, cosa succede se aggiorni la fattoria? Senza sapere quali query memorizzate nella cache contengono la tua farm, sarai costretto a uccidere l'intera cache. Che tipo di controproducente è quello che stai cercando di ottenere.
Posso vedere il ragionamento dietro questo approccio. Uno strato di prestazioni di manutenzione 0. Tuttavia, se i punti di cui sopra non vengono presi in considerazione, l'approccio prima ucciderà le prestazioni, quindi porterà a molti tentativi di mantenerlo, quindi si dimostrerà completamente non-mantenibile.
Sono stato su quella strada. Alla fine ho perso un sacco di tempo e ho rinunciato.
Ho trovato un approccio molto migliore mettendo in cache ciascuna entità risultante separatamente quando i risultati provengono dal back-end con un metodo di estensione per ogni tipo separatamente o tramite un'interfaccia comune.
Quindi è possibile creare un metodo di estensione per le espressioni lambda per provare prima la cache prima di colpire il db.
var query = (x => x.Crops.Any(y => slug == y.Slug) && x.Deleted == false);
var results = query.FromCache();
if (!results.Any()) {
results = query.FromDatabase();
results.ForEach(x = x.ToCache());
}
Naturalmente, sarà ancora bisogno di tenere traccia quali query hanno effettivamente colpito il database per evitare di query Un ritorno 3 allevamenti da DB soddisfacente interrogazione B con una sola azienda agricola corrispondente dalla cache mentre il database sarebbe in realtà avere 20 aziende agricole corrispondenti a disposizione. Quindi, ogni query deve necessariamente premere DB almeno una volta.
E devi tenere traccia delle query che restituiscono 0 risultati per evitare che colpiscano di conseguenza il DB per nulla.
Ma, tutto sommato, si ottiene via con molto meno codice e come bonus, quando si aggiorna una fattoria, è possibile
var farm = (f => f.farmId == farmId).FromCache().First();
farm.Name = "My Test Farm";
var updatedFarm = farm.ToDatabase();
updatedFarm.ToCache();
che cosa è sbagliato con l'utilizzo di il metodo 'GetHashCode()' e un 'HashSet'? Non è univoco, ma un 'HashSet' è in molti casi in grado di ricevere e aggiungere elementi in O (1). –
@CommuSoft, non funzionerebbe, perché anche due espressioni che sembrano esattamente uguali non sarebbero considerate uguali (a meno che tu non abbia fornito il tuo comparatore di uguaglianza). – svick
@CommuSoft - Inoltre, un hashcode non è garantito e quindi un potenziale bug nel codice – Polity