使用最小缓存锁来实现。在缓存中存储的值被封装在容器中。如果值不在缓存中,则值容器被锁定。仅在创建容器期间才锁定缓存。
public static class CacheExtensions
{
private static object sync = new object();
private class Container<T>
{
public T Value;
}
public static TValue GetOrStore<TValue>(this Cache cache, string key, Func<TValue> create, TimeSpan slidingExpiration)
{
return cache.GetOrStore(key, create, Cache.NoAbsoluteExpiration, slidingExpiration);
}
public static TValue GetOrStore<TValue>(this Cache cache, string key, Func<TValue> create, DateTime absoluteExpiration)
{
return cache.GetOrStore(key, create, absoluteExpiration, Cache.NoSlidingExpiration);
}
public static TValue GetOrStore<TValue>(this Cache cache, string key, Func<TValue> create, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
return cache.GetOrCreate(key, x => create());
}
public static TValue GetOrStore<TValue>(this Cache cache, string key, Func<string, TValue> create, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
var instance = cache.GetOrStoreContainer<TValue>(key, absoluteExpiration, slidingExpiration);
if (instance.Value == null)
lock (instance)
if (instance.Value == null)
instance.Value = create(key);
return instance.Value;
}
private static Container<TValue> GetOrStoreContainer<TValue>(this Cache cache, string key, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
var instance = cache[key];
if (instance == null)
lock (cache)
{
instance = cache[key];
if (instance == null)
{
instance = new Container<TValue>();
cache.Add(key, instance, null, absoluteExpiration, slidingExpiration, CacheItemPriority.Default, null);
}
}
return (Container<TValue>)instance;
}
}
Repository.GetUser(_userId)
(即使数据已经在缓存中存在)。这是正常的吗? - Chase Florellvar result = cache[key];
这一行上设置断点,并检查缓存中的值。如果你在那里找不到它,就逐步执行并观察缓存中的值被设置。然后再次检查缓存是否存在该值。如果没有,则说明你有一个严重的问题。如果有,可能是由于系统资源不足而导致缓存被清空。请参考Andrei的评论以了解如何更改缓存过期值。 - user1228