Lassen Sie mich zunächst einmal wissen, dass der folgende Code nicht threadsicher ist (Korrektur: möglicherweise). Ich habe Probleme damit, eine Implementierung zu finden, die tatsächlich getestet werden kann. Ich überarbeite gerade ein großes WCF-Projekt, für das einige (meistens) statische Daten zwischengespeichert und aus einer SQL-Datenbank ausgefüllt werden müssen. Es muss mindestens einmal am Tag ablaufen und "aktualisiert" werden, weshalb ich MemoryCache verwende.
Ich weiß, dass der folgende Code nicht threadsicher sein sollte, aber ich kann nicht erreichen, dass er unter hoher Last fehlschlägt und um die Sache zu komplizieren. Eine Google-Suche zeigt Implementierungen in beide Richtungen (mit und ohne Sperren kombiniert mit Debatten, ob sie notwendig sind oder nicht).
Könnte jemand mit Kenntnissen über MemoryCache in einer Umgebung mit mehreren Threads mich definitiv wissen lassen, ob ich gegebenenfalls sperren muss, damit ein zu entfernender Aufruf (der selten aufgerufen wird, aber erforderlich ist) beim Abrufen / erneuten Auffüllen nicht ausgelöst wird.
public class MemoryCacheService : IMemoryCacheService
{
private const string PunctuationMapCacheKey = "punctuationMaps";
private static readonly ObjectCache Cache;
private readonly IAdoNet _adoNet;
static MemoryCacheService()
{
Cache = MemoryCache.Default;
}
public MemoryCacheService(IAdoNet adoNet)
{
_adoNet = adoNet;
}
public void ClearPunctuationMaps()
{
Cache.Remove(PunctuationMapCacheKey);
}
public IEnumerable GetPunctuationMaps()
{
if (Cache.Contains(PunctuationMapCacheKey))
{
return (IEnumerable) Cache.Get(PunctuationMapCacheKey);
}
var punctuationMaps = GetPunctuationMappings();
if (punctuationMaps == null)
{
throw new ApplicationException("Unable to retrieve punctuation mappings from the database.");
}
if (punctuationMaps.Cast<IPunctuationMapDto>().Any(p => p.UntaggedValue == null || p.TaggedValue == null))
{
throw new ApplicationException("Null values detected in Untagged or Tagged punctuation mappings.");
}
// Store data in the cache
var cacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTime.Now.AddDays(1.0)
};
Cache.AddOrGetExisting(PunctuationMapCacheKey, punctuationMaps, cacheItemPolicy);
return punctuationMaps;
}
//Go oldschool ADO.NET to break the dependency on the entity framework and need to inject the database handler to populate cache
private IEnumerable GetPunctuationMappings()
{
var table = _adoNet.ExecuteSelectCommand("SELECT [id], [TaggedValue],[UntaggedValue] FROM [dbo].[PunctuationMapper]", CommandType.Text);
if (table != null && table.Rows.Count != 0)
{
return AutoMapper.Mapper.DynamicMap<IDataReader, IEnumerable<PunctuationMapDto>>(table.CreateDataReader());
}
return null;
}
}