使用HttpContext.Current.Application存储简单数据

我想在我的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"]

这样做有什么缺点吗? 看起来它会对我想要实现的目标起作用,但是有没有人知道更好的方法来做到这一点,假设我已经列出的方法有一些主要的缺点?

你实际做的是缓存 ,它很棒,因为你减少了对外部存储(数据库或文件,无论如何)的调用。 当然,权衡是内存使用。 现在,几乎任何现代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; 

这种方法更好,因为您具有类型安全性,因为可以使用确切类型显式声明此公共静态属性。 此外,这种存储更加可测试,因为它不依赖于Web上下文。

HTH!

HttpContext.Current.Application本质上是向后兼容经典ASP所需的宿醉。 它本质上是一个静态Hashtable,具有经典的ASP锁定语义(Application.Lock / Application.UnLock)。

作为弱类型的Hashtable,您需要转换您检索的对象:

 MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"]; 

在不是从传统ASP迁移的ASP.NET应用程序中,我更喜欢使用其他标准.NET内容,例如:

  • 一个静态字段,如果需要锁定,则使用.NET锁定语义(例如,C#lock关键字或ReaderWriterLockSlim实例,具体取决于您的要求):

    static MyObject myObject = LoadFromSql();

  • ASP.NET缓存 – 具有丰富的function,用于管理过期,依赖,…

如果您要部署到单个Web服务器,该方法将起作用。 请考虑Cache对象,因为如果您需要此类function,它会提供更多的到期选项。 (参见比较,虽然是老年人,但在这里 。)

如果您要部署到Web服务器场或等效服务器,则应使用memcached或其他Web场友好缓存机制。 Application和Cache对象通常只存在于单个服务器上下文中; 如果您的用户可能在会话期间遇到多个Web服务器(并且缓存需要相同),则您需要一个可从每个潜在Web服务器看到的共享缓存。

无论您采用哪种路径,只要基础数据发生变化,您就需要使缓存无效/重新加载,这是自定义代码因应用而异。

这种方法效果很好,并且可以大大加快速度,但是乍一看它比你可能意识到的要多一些……

是的,使用HttpContext.Current.Application可以正常工作。 没问题。

“HttpContext.Current.Application”只是对Web应用程序中.NET的静态全局“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值,可以安全地检查它们的值或从数据库中更新它们,或相互更新和检查,协同工作。 我通常创建一个静态全局类来帮助管理和检索我存储的Application变量。 通过这种方式,您既可以使用HttpApplicationState类的状态字典,也可以使用Web应用程序静态对象来共享和维护全局值。 (请记住,每个工作进程都会分配每个静态类,并且在许多IIs Web服务器/ Web应用程序上,默认情况下平均可能有多达10个WP。因此,将静态类型的数据保持在最低限度。)

请记住,因为一些提到的服务器场不共享应用程序状态。 有很多方法可以解决这个问题。 我不是缓存的粉丝,因为它可能会过期,失败,变得陈旧或被破坏。 一个更简单的解决方案是简单地使用数据库和url查询字符串来跨服务器进行通信并维护状态。 祝好运!

Application_Start实际上只会在App Pool Recylce,IIS Resets或重新启动时被触发。 如果您不经常更新这些值,为什么不将它们存储在您的web.config中并以这种方式访问​​它们?

话虽如此,我认为你的方法没有任何问题 。 虽然更典型的是我看到人们使用配置文件很少更改值。