2017-01-23 34 views
0

我想構建一個MVC應用程序,用.NET Framework 4.0的緩存機制替換會話對象。使用MemoryCache的C#MVC替換會話

應用程序必須在某種緩存中存儲一​​些值以保持數據庫流量和加載時間較低(例如設置,下拉值等)。用戶使用用戶名和密碼驗證他們自己。這裏使用默認的FormsAuthentication。我的想法是爲每個用戶創建一個獨特的MemoryCache,併爲應用程序創建一個通用的MemoryCache

我對用戶MemoryCache吸氣看起來像這樣

private MemoryCache _memCache 
{ 
    get 
    { 
     if(HttpContext.Application[User.Identity.Name] == null) 
     { 
      HttpContext.Application[User.Identity.Name] = new MemoryCache(User.Identity.Name); 
     } 

     return HttpContext.Application[User.Identity.Name] as MemoryCache; 
    } 
} 

如果用戶退出的緩存將被佈置。

這是應用程序

private MemoryCache _appMemCache 
{ 
    get 
    { 
     if(HttpContext.Application["ApplicationMemoryCache"] == null) 
     { 
      HttpContext.Application["ApplicationMemoryCache"] = new MemoryCache("ApplicationMemoryCache"); 
     } 

     return HttpContext.Application["ApplicationMemoryCache"] as MemoryCache; 
    } 
} 

的問題是,如果應用程序對象可用來存儲MemoryCache全球MemoryCache。如果CacheItemPolicy沒有這個問題的工作。

我不使用會話的原因是可能的超時和阻塞並行請求。

+0

請參閱[考慮使用會話狀態](https://brockallen.com/2012/04/07/think-twice-about-using-session-state/) - 它明確指出會話狀態不是存放用戶資料數據的地方。但我同意@ChrisPratt,你應該瞄準消除或最小化會話狀態的使用,而不是拿出精心設計的方法來取代它。 – NightOwl888

回答

1

由於多種原因,這是一個壞主意。首先,最重要的是,MemoryCache既是易失性的,也是流程限制的。即使存儲在proc中,但仍會保留會話數據的一些嘗試,但緩存被認爲是完全一次性的。如果內存不足,它將立即被丟棄。此外,這將有效地消除任何將應用擴展到多個工作人員(進程)的能力,因爲每個工作人員都擁有緩存版本,這意味着用戶的「會話」是否已恢復,取決於運行的平局他們在下一次請求時登錄了哪個進程。

不只是使用會話的原因沒有任何意義。是的,會話超時,但是這些有點固定,假設你沒有在proc中使用。即使在proc中,只要App Pool回收或類似的事情沒有發生,會話就會以固定的時間間隔超時。相反,MemoryCache隨時可能在處消失。對於數據持續多久或者甚至會持續多長時間沒有保證。僅僅因爲你把它設置爲一年左右,並不意味着它不會在五分鐘內被丟棄,這取決於系統中還在發生什麼。

就「阻止並行請求」而言,我不確定你在說什麼。會話是線程安全的,理論上應允許並行請求。任何異步處理都會遇到併發問題,例如寫入會話存儲區,但同樣存在的問題也會存在於MemoryCache中。儘管如此,你談論的保存事情實際上並不屬於會話,反正,儘管如此。雖然你使用類似MemoryCache的原因是完全無效的,但實際上你應該使用緩存來存儲這種類型的東西。換句話說,只需使用緩存,不要嘗試以某種方式將緩存替換爲會話。

另外,正如我前面提到的,在多進程場景中存在MemoryCache的嚴重問題。如果您正在構建的應用程序只能服務於少數用戶,則應完全避免使用MemoryCache,而應使用類似Redis的應用程序。Redis被微軟Azure使用,所以它得到了微軟的很好的支持並且集成到了ASP.NET中,但是你可以選擇任何NoSQL解決方案。

+0

asp.net每次(可寫)會話使用一個線程,一次限制一個請求上的用戶。這是我想阻止的事情。你能指定爲什麼我的數據不屬於會話(例如下拉值)。 – JoeJoe87577

+0

這根本不正確。我不確定你從哪裏得到這些信息。至於爲什麼你不應該爲這些數據使用會話,一般來說,你應該使用會話的時間很少。如果數據屬於特定用戶,您可以稍後再從用戶那裏獲取。會話只應用於特定於實際需要*的匿名用戶的數據,以便在請求之間保留。像下拉選擇一樣的東西不會檢查那些盒子。您可能需要*緩存*,以避免往返數據庫,但它不屬於會話。 –

+0

@ChrisPratt - 說使用ObjectCache不會擴展到多個進程是不正確的 - 你可以使用[distributed ObjectCache](http://stackoverflow.com/questions/14646658/i-am-looking-for -a-distributed-data-object-cache-for-my-asp-net-mvc-app)來處理這個問題。但是,比使用進程外會話狀態還是像Redis這樣的事情是值得的額外努力?可能不會。 – NightOwl888