我希望在触摸特定文件时回收ASP.NET缓存项,但以下代码无效:
HttpContext.Current.Cache.Insert(
"Key",
SomeObject,
new CacheDependency(Server.MapPath("SomeFile.txt")),
DateTime.MaxValue,
TimeSpan.Zero,
CacheItemPriority.High,
null);
当我点击缓存时,似乎没有检查“SomeFile.txt”,并且修改它不会导致此项无效。
我做错了什么?
答案 0 :(得分:5)
这是一个独特而有趣的问题,因此我将在此处记录原因和解决方案作为答案,供未来的搜索者使用。
我在问题中遗漏的一点是,这个缓存插入是在实现单例模式的服务类中发生的。
简而言之:
public class Service
{
private static readonly Service _Instance = new Service();
static Service () { }
private Service () { }
public static Service Instance
{
get { return _Instance; }
}
// The expensive data that this service exposes
private someObject _data = null;
public someObject Data
{
get
{
if (_data == null)
loadData();
return _data;
}
}
private void loadData()
{
_data = GetFromCache();
if (_data == null)
{
// Get the data from our datasource
_data = ExpensiveDataSourceGet();
// Insert into Cache
HttpContext.Current.Cache.Insert(etc);
}
}
}
对某些人来说可能是显而易见的,但这里的罪魁祸首是单身模式中的延迟加载。我陷入困境,认为缓存没有失效,我忘记了只要工作进程存活,单例的状态就会持续存在。
Cache.Insert有一个重载,它允许你为删除缓存项时指定一个事件处理程序,我的第一个测试是创建一个虚拟处理程序并在其中设置一个断点。一旦我看到缓存被清除,我意识到“_data”没有被重置为null,所以对单例的下一个请求加载了延迟加载的值。
从某种意义上说,我是双重缓存,虽然单例缓存非常短暂,但足够长,令人讨厌。
解决方案?
HttpContext.Current.Cache.Insert(
"Key",
SomeObject,
new CacheDependency(Server.MapPath("SomeFile.txt")),
DateTime.MaxValue,
TimeSpan.Zero,
CacheItemPriority.High,
delegate(string key, object value, CacheItemRemovedReason reason)
{
_data = null;
}
);
清除缓存后,还必须清除单例内的状态...问题已解决。
在这里学到的经验?不要把状态置于单身。
答案 1 :(得分:1)
ASP.NET是否在具有CacheDependency中指定的文件的适当权限的帐户下运行?如果没有,那么这可能是CacheDependency无法正常工作的原因之一。
答案 2 :(得分:0)
我认为您需要指定路径:
var d = new CacheDependency(Server.MapPath("SomeFile.txt"));
根据需要预先加~\App_Data
。
答案 3 :(得分:0)
您的代码对我来说很好。然而,除了这个片段之外,任何事情都可能发生。
您是否有机会重新插入每个回发?
尝试将缓存依赖项设置为类字段,并在每次回发时检查它。修改之间的文件,看看它是否记录为“已更改”。 e.g:
public partial class _Default : System.Web.UI.Page
{
CacheDependency dep;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dep = new CacheDependency(Server.MapPath("SomeFile.txt"));
HttpContext.Current.Cache.Insert(
"Key",
new Object(),
dep,
DateTime.MaxValue,
TimeSpan.Zero, CacheItemPriority.High, null);
}
if (dep.HasChanged)
Response.Write("changed!");
else
Response.Write("no change :("); }}
答案 4 :(得分:0)
我能够重现此行为的唯一方法是,如果提供给CacheDependency的构造函数的路径不存在。如果路径不存在,CacheDependency不会抛出异常,因此可能会产生一些误导。