2010-06-21 171 views
9

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

我正在考虑使用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"]

有没有这样做的缺点?看起来它对我所要达到的目标会很好,但是有没有人知道有更好的方法可以做到这一点,假设我已经布置了这个方法有一些主要的缺点?

+1

列表更新时会发生什么?你打算每次重置应用程序吗? – 2010-06-21 03:38:16

回答

27

你实际上做的是缓存,这是伟大的,因为你减少到外部存储调用(数据库或文件,等等)。当然,权衡是内存使用。现在,几乎所有现代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!

+0

谢谢,这就是我一直在寻找的东西。 – macca1 2010-06-22 02:43:19

+0

真的非常感谢!对我有帮助。 但在我的情况下(ASP.NET API),我必须在内存上存储更大的数据(从现在(和计数),这是超过10,000条记录 - 存储在列表/字典中的更大的数据。我应该去你的方法 – hungdoan 2013-08-06 08:48:35

+1

@hungdoan,我会使用MemCache这样的解决方案 - 一个外部缓存服务,我认为在ASP.NET应用程序中存储超过1 GB的缓存是个不错的主意。 – 2013-08-06 20:29:34

0

Application_Start真的只会被App Pool Recylce's,IIS重置或重启。如果您不经常更新这些值,为什么不将它们存储在web.config中并以这种方式访问​​它们?

这就是说,我不认为有什么错误用你的方法。虽然更通常我见过使用配置文件的人很少更改值。

3

如果您正在部署到单个Web服务器,则此方法可行。考虑一下Cache对象,因为如果你需要这样的功能,它提供了更多的过期选项。 (请参阅比较,尽管是一个老年人,here。)

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

无论您采用哪种路径,只要底层数据发生更改(根据应用程序而定制的自定义代码),就需要无效化/重新加载缓存。

这种方法效果很好,可以大大加快的东西,但它更多的工作比你第一眼实现...

+0

感谢您的深刻解答。我只部署到一台服务器,但这对于Web服务器场来说很有意思。 – macca1 2010-06-22 02:43:01

6

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

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

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

在ASP.NET应用程序,是不是从传统的ASP迁移,我宁愿用其他标准.NET的东西,如:

  • 静态字段,使用.NET锁定机制,如果你需要锁定(如C#lock关键字,或ReaderWriterLockSlim实例,根据您的要求):

    static MyObject myObject = LoadFromSql();

  • ASP.NET缓存 - 这对于管理期满,相关性,丰富的功能...

2

是,使用HttpContext.Current.Application将正常工作的你在做什么。没问题。

“HttpContext.Current.Application”只是对.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值,可以安全地检查值或从数据库更新它们,或者相互更新和检查,并行工作。我通常创建一个静态全局类来协助管理和检索我存储的应用程序变量。通过这种方式,您可以同时使用HttpApplicationState类的状态字典和Web应用程序静态对象共同工作来共享和维护全局值。(请记住,每个工作进程都分配了每个静态类,并且在许多IIs Web服务器/ Web应用程序中默认情况下平均可以有多达10个WP。因此,将静态类型的数据降至最低)。考虑到一些提到的服务器场不共享应用程序状态。有很多方法来管理这个。由于可能过期,失败,陈旧或损坏的方式,我不喜欢缓存。一个更简单的解决方案是简单地使用数据库和url querystrings跨服务器进行通信并维护状态。祝你好运!

+0

对于放入'System.Web.HttpContext.Current.Application'条目的数据是否存在最大大小限制。例如,一个50MB的条目? – Heinrich 2017-09-23 03:44:48

相关问题