2009-04-29 26 views
3

我想回收一個ASP.NET緩存項,當一個特定的文件被觸摸,但下面的代碼是不工作:ASP.NET緩存和文件的依賴關係

     HttpContext.Current.Cache.Insert(
          "Key", 
          SomeObject, 
          new CacheDependency(Server.MapPath("SomeFile.txt")), 
          DateTime.MaxValue, 
          TimeSpan.Zero, 
          CacheItemPriority.High, 
          null); 

「SomeFile.txt」不似乎在我點擊緩存時進行檢查,並且修改它不會導致此項無效。

我在做什麼錯?

+0

什麼是ObjectFile?一個字符串? – 2009-04-29 23:58:15

+0

我編輯,使其更加明顯。 – FlySwat 2009-04-29 23:59:35

回答

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); 
      } 
     } 
} 

可能明顯一些,但這裏的罪魁禍首是Singleton模式中延遲加載。我很想到緩存沒有失效,我忘記了只要工作進程還活着,單例狀態就會一直存在。

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; 
     } 
); 

當緩存被清除時,單例中的狀態也必須被清除......問題解決了。

在這裏學到了什麼?不要將狀態置於單身狀態。

0

我認爲你需要指定一個路徑:

var d = new CacheDependency(Server.MapPath("SomeFile.txt")); 

前面加上~\App_Data需要。

+0

我已經通過了一條完整的道路,對不起,這個人爲的例子並不清楚。 – FlySwat 2009-04-30 01:15:20

0

你的代碼對我來說看起來很好。然而,除了這個片段之外,任何事情都可能發生。

  • 您是否重新插入每次回發?

  • 嘗試使緩存依賴項成爲類字段,並在每次回發中檢查它。修改兩者之間的文件,看它是否註冊爲「更改」。例如: -

    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 :("); }} 
    
+0

絕對不能在回發上重新插入。這實際上是在圖書館中遠離的抽象方式。 – FlySwat 2009-04-30 03:23:44

1

是ASP.NET的帳戶下運行與在的CacheDependency指定的文件適當的權限?如果沒有,那麼這可能是CacheDependency無法正常工作的一個原因。

+0

是的,因爲它解析該文件以創建原始緩存對象。 – FlySwat 2009-04-30 19:47:10

0

我能夠重現此行爲的唯一方法是如果提供給CacheDependency的構造函數的路徑不存在。如果路徑不存在,CacheDependency不會拋出異常,所以它可能有點誤導。

+0

但是,我打開這個文件(並使用相同的確切路徑變量)一行,並將其讀入緩存對象。 – FlySwat 2009-05-04 22:50:53