2011-05-13 67 views
23

长时间监听 - 第一次来电。我希望得到一些建议。我一直在阅读有关.net的缓存 - 无论是与System.Web.Caching和System.Runtime.Caching。我想知道我可以获得什么额外的好处,与简单地创建一个带锁定的静态变量。我现在的(头脑简单的)高速缓存方法是这样的:为什么要使用System.Runtime.Caching或System.Web.Caching Vs静态变量?

public class Cache 
{ 
    private static List<Category> _allCategories; 
    private static readonly object _lockObject = new object(); 

    public static List<Category> AllCategories 
    { 
     get 
     { 
      lock (_lockObject) 
      { 
       if (_allCategories == null) 
       { 
        _allCategories = //DB CALL TO POPULATE 
       } 
      } 
      return _allCategories; 
     } 
    } 
} 

除了到期(我不希望这个过期)我很茫然,看看有什么的使用内置的缓存的益处是。

也许对不适用于我的更复杂的缓存方案有好处 - 或者我只是错过了某些东西(不会是第一次)。

那么,如果我想要一个永不过期的缓存,那么使用缓存有什么优势?不是静态变量这样做吗?

+0

我认为你的锁块应该包含if语句。否则,您可能会遇到不止一次从db加载的情况。 – row1 2011-05-13 01:52:52

+0

你是对的 - 对不起 - 有点草率写一个简单的例子。我在原来的问题中改变了它。 – sfsr 2011-05-13 01:57:04

回答

19

首先,Xaqron提出了一个很好的观点,即您所谈论的内容可能不符合缓存条件。这实际上只是一个懒惰的全局访问变量。这很好:作为一个实用的程序员,没有必要向后弯曲来实现完全缓存,而这并不是真正有益的。如果你打算使用这种方法,不过,你很可能会成为Lazy,让.NET 4做繁重:

private static Lazy<IEnumerable<Category>> _allCategories 
    = new Lazy<IEnumerable<Category>>(() => /* Db call to populate */); 

public static IEnumerable<Category> AllCategories 
{ 
    get { return _allCategories.Value; } 
} 

我改变了类型IEnumerable<Category>,以防止用户思维的自由他们可以添加到这个列表中。这就是说,无论您何时访问公共静态成员,您都错过了面向对象编程所提供的大量灵活性。我个人建议你:

  1. 重命名类CategoryRepository(或类似的东西),
  2. 产生这个类实现一个ICategoryRepository界面,在界面上一个GetAllCategories()方法,并
  3. 有无这个接口被构造器注入到任何需要它的类中。

这种方法将使您可以对所有类别应该做的事情进行单元测试,并完全控制测试哪些“类别”,而无需数据库调用。

+1

我同意“缓存”可能不是正确的词 - 但“懒惰加载全局可访问的变量”不会滚动更大的问题:)我没有听说过懒惰之前,我会用它每当我需要一个懒惰的加载变量。 – sfsr 2011-05-13 14:40:36

19

System.Runtime.Caching和System.Web.Caching有自动失效控制,可以根据是文件改变SQL Server数据库的变化,你可以实现自己的“改变供应商” 。你甚至可以在缓存条目之间创建依赖关系。

请参阅此链接了解更多关于System.Caching命名空间:

http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx

所有我所提到的功能中的链接被记录在案。

使用静态变量需要手动控制过期,并且您必须使用文件系统观察器和其他在高速缓存命名空间中提供的观察器。

+2

哇 - 你们都快:)这是一个很好的观点。 在更复杂的情况下,我完全可以看到这种需求 - 但假设原始问题中的类别列表是固定列表(意味着更改将非常罕见),并且我不希望它过期 - 我假设维护到期控制所需的额外开销实际上是使用静态变量的投票,因为在这种情况下它们会更高效。 顺便说一句 - 我想讨论这个问题,并且想深入研究这些类型的事情 - 我不想固执 - 只是在另一边做案例。 – sfsr 2011-05-13 02:03:36

+3

我认为如果你不需要他们的服务,你不应该将自己绑定到框架上。如果您不需要过期控制,也不需要缓存系统的其他服务,那么请不要使用它。但是,如果你需要,不要重新发明轮子。那当然是我的观点!有些人可能会不同意。 – 2011-05-13 02:09:45

+0

我认为这是一个非常有效的解决方案,在您提供的情况下使用静态变量。 =) – 2011-05-13 02:10:48

3

Other than expiration (and I wouldn't want this to expire) ...

如果你不关心的寿命时的名字是不是caching了。

仍然使用Application(您的情况)和Session对象是存储应用程序级别和会话级别数据的最佳实践。

+1

我认为你说得对,关于缓存不是正确的词 - 我的意思是说,数据库结果保存在本地内存中,而不是每次需要时都去缓慢的介质。至于应用程序对象 - 我不同意这一点。这里引用的MSDN文章[链接](http://stackoverflow.com/questions/303725/asp-net-application-state-vs-a-static-object/303787#303787)表示,它是更经典的asp迁移。 – sfsr 2011-05-13 14:45:05

+0

ASP classic基于模块化编程。所以对于模块之间的通信应用范围变量(如C)是选项。您正在将数据库中的类别加载到内存以便快速访问。如果您希望更改反映类别的数据库,则需要根据某些条件(时间,触发器...)更新缓存类,然后根据含义进行缓存。缓存更多的是繁重而冗长的操作,即当您在我的电脑中看到使用的驱动器和可用空间时。在股市网站上,计算每个请求的一年更改并不明智。你可以每天做一次。 – Xaqron 2013-03-28 19:32:10