2011-11-09 50 views
1

我們正在重構我們的網站以使用外部緩存,並且我們採取的第一步是使用自定義OutputCacheProvider。首先,我們創建了一個簡單的提供程序,它只是包裝MemoryCache,並發現我們管理依賴關係的方式存在問題。使用ASP.NET自定義更改實體時頁面失效OutputCacheProvider

我們有一個自定義OutputCacheAttribute,增加了一個額外的關鍵依賴於能夠在某些實體變爲無效一組頁面,並保持這個功能我看到一些選項:

  1. 手動刪除CachedVary那ASP.NET存儲在緩存中,假設密鑰爲"a2" + query"。這似乎工作,但我不確定可靠性。

  2. 添加包含必須從緩存中逐出的頁面數組的高速緩存鍵,然後刪除該鍵使用外部緩存鍵相關性功能(如果有)。這應該足以模仿我們使用的關鍵依賴關係,但採用更復雜的方式。

  3. 忘掉這個,放上一個簡短的高速緩存期,讓它們過期而不用擔心太多。

  4. 做我們自己的頁面緩存,忘記ASP.NET輸出緩存,不太吸引人。

我確定還有其他方法。任何提示,經驗或建議?

回答

1

我用我們採用的解決方案回答我自己的問題。

在我們的OutputCacheAttribute中,我們添加一個空的緩存對象,其中包含一個取決於請求的URL和一些參數的鍵。這將用於使外部頁面無效。

然後,我們還添加另一個對象,其中包含一個取決於當前請求幷包含前一個cacheKey的鍵。

最後,建立一個靜態的ValidationCallback。回調獲取當前請求的關鍵字值,這是依賴關鍵字。然後,如果它不爲null,則獲取依賴項的值,如果爲null,則依賴項已被逐出,並將validationStatus設置爲HttpValidationStatus.Invalid

一些代碼來說明:

public override void OnResultExecuting(ResultExecutingContext filterContext) 
{ 
    base.OnResultExecuting(filterContext); 

    // Build dependencies 
    BuildDependencies(paramsToDepend, filterContext.Controller, this.Duration); 
} 

private void BuildDependencies(IEnumerable<string> paramsToDepend, ControllerBase controller, int duration) 
{ 
    string[] valuesToInclude = GetValuesToInclude(paramsToInclude, controller.ControllerContext); 

    // Build the caché key for the current request 
    var cacheKey = CacheKeyProvider.GetCacheKeyFor(controller, paramsToDepend); 

    var cache = controller.ControllerContext.HttpContext.Cache; 
    var cacheValue = cache.Get(cacheKey); 

    if (cacheValue == null) 
    { 
     // The key is created if not exists 
     Provider.Add(cacheKey, new object(), Context.CurrentDateTime.AddSeconds(duration).ToUniversalTime()); 
    } 

    // Add the dependency 
    Provider.Set(CachePrefix + controller.ControllerContext.HttpContext.Request.Path, cacheKey, Context.CurrentDateTime.AddSeconds(duration).ToUniversalTime()); 

    // Register callback 
    controller.ControllerContext.HttpContext.Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(ValidationCallback), null); 
} 

public static void ValidationCallback(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
{ 
    var provider = OutputCache.Providers[OutputCache.DefaultProviderName]; 

    var dependency = provider.Get(CachePrefix + context.Request.RawUrl) as string; 

    if (dependency == null) return; 

    var depValue = provider.Get(dependency); 

    // If it's null, someone has invelidated the caché (an entity was modified) 
    if (depValue == null) 
    { 
     validationStatus = HttpValidationStatus.Invalid; 
    } 
} 
相關問題