Mise en cache dans une application console

J’ai besoin de mettre en cache une liste générique afin de ne pas avoir à interroger la firebase database plusieurs fois. Dans une application Web, je l’appendais simplement à httpcontext.current.cache . Quelle est la bonne façon de mettre en cache des objects dans les applications de la console?

Conservez-le en tant que membre d’instance de la classe contenant Cela ne peut pas être fait dans une application Web, car l’object de la classe de page est recréé à chaque demande.

Cependant, .NET 4.0 a également une classe MemoryCache à cette fin.

Dans une variable de classe. Vraisemblablement, dans la méthode main de votre application de console, vous instanciez au moins un object. Dans la classe de cet object, vous déclarez une variable de niveau classe (une List ou autre) dans laquelle vous mettez en cache tout ce qui nécessite une mise en cache.

Voici une classe de cache très simple que j’utilise dans les consoles et qui est auto-nettoyable et facile à implémenter.

L’usage:

 return Cache.Get("MyCacheKey", 30, () => { return new Model.Guide().ChannelListings.BuildChannelList(); }); 

La classe:

  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Timers; namespace MyAppNamespace { public static class Cache { private static Timer cleanupTimer = new Timer() { AutoReset = true, Enabled = true, Interval = 60000 }; private static readonly Dictionary internalCache = new Dictionary(); static Cache() { cleanupTimer.Elapsed += Clean; cleanupTimer.Start(); } private static void Clean(object sender, ElapsedEventArgs e) { internalCache.Keys.ToList().ForEach(x => { try { if (internalCache[x].ExpireTime <= e.SignalTime) { Remove(x); } } catch (Exception) { /*swallow it*/ } }); } public static T Get(ssortingng key, int expiresMinutes, Func refreshFunction) { if (internalCache.ContainsKey(key) && internalCache[key].ExpireTime > DateTime.Now) { return (T)internalCache[key].Item; } var result = refreshFunction(); Set(key, result, expiresMinutes); return result; } public static void Set(ssortingng key, object item, int expiresMinutes) { Remove(key); internalCache.Add(key, new CacheItem(item, expiresMinutes)); } public static void Remove(ssortingng key) { if (internalCache.ContainsKey(key)) { internalCache.Remove(key); } } private struct CacheItem { public CacheItem(object item, int expiresMinutes) : this() { Item = item; ExpireTime = DateTime.Now.AddMinutes(expiresMinutes); } public object Item { get; private set; } public DateTime ExpireTime { get; private set; } } } } 
 // Consider this psuedo code for using Cache public DataSet GetMySearchData(ssortingng search) { // if it is in my cache already (notice search criteria is the cache key) ssortingng cacheKey = "Search " + search; if (Cache[cacheKey] != null) { return (DataSet)(Cache[cacheKey]); } else { DataSet result = yourDAL.DoSearch(search); Cache[cacheKey].Insert(result); // There are more params needed here... return result; } } 

Réf.: Comment mettre en cache un jeu de données pour arrêter les allers-retours à la firebase database?

Il existe de nombreuses façons d’implémenter les caches, en fonction de ce que vous faites exactement. Habituellement, vous utiliserez un dictionnaire pour conserver les valeurs en cache. Voici ma simple implémentation d’un cache, qui ne cache des valeurs que pour un temps limité:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CySoft.Collections { public class Cache { private readonly Dictionary _cache = new Dictionary(); private TimeSpan _maxCachingTime; ///  /// Creates a cache which holds the cached values for an infinite time. ///  public Cache() : this(TimeSpan.MaxValue) { } ///  /// Creates a cache which holds the cached values for a limited time only. ///  /// Maximum time for which the a value is to be hold in the cache. public Cache(TimeSpan maxCachingTime) { _maxCachingTime = maxCachingTime; } ///  /// Tries to get a value from the cache. If the cache contains the value and the maximum caching time is /// not exceeded (if any is defined), then the cached value is returned, else a new value is created. ///  /// Key of the value to get. /// Function creating a new value. /// A cached or a new value. public TValue Get(TKey key, Func createValue) { CacheItem cacheItem; if (_cache.TryGetValue(key, out cacheItem) && (DateTime.Now - cacheItem.CacheTime) <= _maxCachingTime) { return cacheItem.Item; } TValue value = createValue(); _cache[key] = new CacheItem(value); return value; } private struct CacheItem { public CacheItem(TValue item) : this() { Item = item; CacheTime = DateTime.Now; } public TValue Item { get; private set; } public DateTime CacheTime { get; private set; } } } } 

Vous pouvez transmettre une expression lambda à la méthode Get, qui extrait les valeurs d'une firebase database, par exemple.

Vous pourriez peut-être simplement utiliser un dictionnaire simple. Ce qui rend le cache si spécial dans l’environnement Web, c’est qu’il persiste et que sa scope est telle que de nombreux utilisateurs peuvent y accéder. Dans une application console, vous n’avez pas ces problèmes. Si vos besoins sont assez simples, le dictionnaire ou des structures similaires peuvent être utilisés pour rechercher rapidement les valeurs que vous extrayez d’une firebase database.