[英]Using HttpContext.Current.Application to store simple data
我想在我的 ASP.NET MVC 應用程序中存儲一個簡單對象(包含三個字符串)的小列表。 該列表是從數據庫加載的,很少通過編輯站點管理區域中的某些值來更新。
我正在考慮使用HttpContext.Current.Application
來存儲它。 這樣我就可以在 Global.asax 中加載它:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
HttpContext.Current.Application["myObject"] = loadDataFromSql(); // returns my object
}
然后可以根據需要輕松地從任何控制器或視圖中引用它。 然后在事件中,管理區域調用updateMyObject
控制器操作,我可以更新數據庫並再次加載它並替換HttpContext.Current.Application["myObject"]
。
這樣做有什么缺點嗎? 似乎它可以很好地滿足我想要實現的目標,但是有沒有人知道更好的方法來做到這一點,假設我提出的方法存在一些主要缺點?
您實際做的是Caching ,這很棒,因為您減少了對外部存儲(數據庫或文件,等等)的調用。 當然,權衡是內存使用。 現在,幾乎所有現代 Web 框架,包括 ASP.NET,都包含某種緩存機制。 要么使用它,要么使用某種全局變量。
將數據存儲在 ASP.NET 的內置Cache
對象中具有一些顯着的優勢,因為這種機制實際上會檢查內存使用情況並根據某些規則刪除緩存的數據。
但是,如果您要緩存的數據在整個應用程序中被大量使用,並且其大小不是太大(例如,小於 1 MB),您可能希望將其存儲為全局變量。
在 ASP.NET 中,全局變量是通過使用Application
對象(如您在問題中描述的)或通過在內部/公共類中編寫公共靜態屬性/字段來實現的。
這是我對靜態屬性的解決方案。 請注意,我使用鎖定對象來保護內部數據免受損壞。 它看起來像這樣:
public class WhateverClass
{
private static object theLocker = new object();
private static YourDataType theData;
public static YourDataType TheData
{
get
{
lock (theLocker)
{
return theData;
}
}
set
{
lock (theLocker)
{
theData = value;
}
}
}
}
用法很簡單:
第一次,在 Application_Start 中:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
WhateverClass.TheData = loadDataFromSql();
}
在任何控制器中:
var myData = WhateverClass.TheData;
這種方法更好,因為您具有類型安全性,因為可以使用確切類型顯式聲明此公共靜態屬性。 此外,這種存儲更易於測試,因為它不依賴於網絡上下文。
哼!
HttpContext.Current.Application
本質上是與經典 ASP 向后兼容所需的宿醉。 它本質上是一個靜態哈希表,具有經典的 ASP 鎖定語義(Application.Lock / Application.UnLock)。
作為弱類型哈希表,您需要轉換您檢索的對象:
MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"];
在不是從經典 ASP 遷移的 ASP.NET 應用程序中,我更喜歡使用其他標准的 .NET 內容,例如:
一個靜態字段,如果您需要鎖定,則使用 .NET 鎖定語義(例如,C# lock 關鍵字或 ReaderWriterLockSlim 實例,具體取決於您的要求):
靜態 MyObject myObject = LoadFromSql();
ASP.NET 緩存 - 具有豐富的管理過期、依賴、...
是的,使用HttpContext.Current.Application
可以很好地完成您正在做的事情。 沒問題。
HttpContext.Current.Application
只是對 .NET 中 Web 應用程序的靜態全局HttpApplicationState
對象的引用,其中每個 Web 應用程序應該有一個全局實例。 通過在那里存儲數據,您可以提供對全局變量的快速、線程安全的訪問。 確保在更新值時鎖定它們,如下例所示:
System.Web.HttpContext.Current.Application.Lock();
System.Web.HttpContext.Current.Application["WebApplicationPath"] = MyWebApplicationPath;
System.Web.HttpContext.Current.Application.UnLock();
正如其他人所提到的,您還可以在App_Code
或其他文件夾中創建一系列靜態類,並在那里存儲全局靜態值以及您的HttpContext.Current.Application
值,在那里可以安全地檢查值或從數據庫更新它們,或相互更新和檢查,協同工作。 我通常創建一個靜態全局類來協助管理和檢索我存儲的應用程序變量。 通過這種方式,您可以同時使用HttpApplicationState
類的狀態字典和 Web 應用程序靜態對象來共享和維護全局值。 (請記住,每個工作進程都分配了每個靜態類,默認情況下,許多 IIS Web 服務器/Web 應用程序上的平均 WP 可能多達 10 個。因此,將靜態類型的數據保持在最低限度。)
請記住,一些提到的服務器場不共享應用程序狀態。 有很多方法可以管理這個。 我不喜歡緩存,因為它可能會過期、失敗、陳舊或損壞。 一個更簡單的解決方案是簡單地使用數據庫和 URL 查詢字符串來跨服務器通信並維護狀態。 祝你好運!
如果您要部署到單個 Web 服務器,則該方法可行。 為此考慮 Cache 對象,因為如果您需要此類功能,它會提供更多過期選項。 (在這里看一個比較,雖然是一個老的。)
如果您打算部署到網絡服務器場或等效物,您應該使用memcached或其他網絡場友好的緩存機制。 Application 和 Cache 對象通常只存在於單個服務器上下文中; 如果您的用戶在他們的會話期間可能訪問多個 Web 服務器(並且緩存需要相同),您將需要一個可以從每個潛在 Web 服務器看到的共享緩存。
無論您采用哪條路徑,只要基礎數據發生變化,您都需要使緩存失效/重新加載,這是因應用程序而異的自定義代碼。
這種方法效果很好,可以大大加快速度,但它比您乍一看可能意識到的要多一些……
Application_Start 實際上只會在 App Pool Recylce、IIS 重置或重新啟動時觸發。 如果您不經常更新這些值,為什么不將它們存儲在您的 web.config 中並以這種方式訪問它們?
話雖如此,我認為您的方法沒有任何問題。 雖然更常見的是我看到人們使用配置文件來獲取很少更改的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.