ASP.NET缓存和文件依赖性

时间:2009-04-29 23:42:29

标签: asp.net caching file-dependancy

我希望在触摸特定文件时回收ASP.NET缓存项,但以下代码无效:

                       HttpContext.Current.Cache.Insert(
                            "Key",
                            SomeObject,
                            new CacheDependency(Server.MapPath("SomeFile.txt")),
                            DateTime.MaxValue,
                            TimeSpan.Zero,
                            CacheItemPriority.High,
                            null);
当我点击缓存时,似乎没有检查“SomeFile.txt”,并且修改它不会导致此项无效。

我做错了什么?

5 个答案:

答案 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不会抛出异常,因此可能会产生一些误导。