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

mac*_*ca1 11 c# asp.net-mvc httpcontext

我想在我的ASP.NET MVC应用程序中存储一个简单对象(包含三个字符串)的小列表.该列表是从数据库加载的,并且很少通过编辑站点管理区域中的某些值来更新.

我正在考虑使用HttpContext.Current.Application来存储它.这样我可以在Global.asax中加载它:

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);

        HttpContext.Current.Application["myObject"] = loadDataFromSql(); // returns my object
    }
Run Code Online (Sandbox Code Playgroud)

然后可以根据需要从任何控制器或视图轻松引用它.然后,如果管理区域调用updateMyObject控制器操作,我可以更新数据库并再次加载并替换HttpContext.Current.Application["myObject"].

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

Ron*_*ein 32

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

用法很简单:

第一次,在Application_Start中:

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);

    WhateverClass.TheData = loadDataFromSql();
}
Run Code Online (Sandbox Code Playgroud)

在任何控制器:

var myData = WhateverClass.TheData;
Run Code Online (Sandbox Code Playgroud)

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

HTH!

  • @hungdoan,我会使用 MemCache 等解决方案 - 一种外部缓存服务。我认为在 ASP.NET 应用程序中存储超过 1 GB 的缓存用于缓存并不是一个好主意。 (2认同)

Joe*_*Joe 8

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

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

MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"];
Run Code Online (Sandbox Code Playgroud)

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

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

    static MyObject myObject = LoadFromSql();

  • ASP.NET缓存 - 具有丰富的功能来管理过期,依赖,...


Sto*_*ely 5

是的,使用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();
Run Code Online (Sandbox Code Playgroud)

正如其他人提到的,您还可以在App_Code或其他文件夹中创建一系列静态类,并在其中存储全局静态值以及HttpContext.Current.Application值,可以在其中安全地检查它们的值或从数据库中更新它们,或相互检查并相互更新。我通常创建一个静态全局类来协助管理和检索我存储的应用程序变量。这样,您就可以同时使用HttpApplicationState类的状态字典和Web应用程序静态对象来共享和维护全局值。(请记住,每个静态类都是按工作进程分配的,默认情况下,许多IIs Web服务器/ Web应用程序上平均平均可能有多达10个WP。因此,请尽量减少静态类型的数据。)

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