在ASP.NET中使用静态字段缓存大对象是不好的做法吗?

时间:2014-07-29 22:18:57

标签: c# asp.net .net caching static-members

我最近在阅读ASP.NET的缓存策略时已经阅读了很多内容,而我从未提到过使用静态字段作为缓存存储的方法。这是一种不好的做法,如果是这样,为什么?以下是我通常如何使用它的示例:

public static Class Repository {
    private static object _lockObject = new object();
    private static List<Products> _products = null;
    public static void GetProducts() {
        if (_products != null) { return _products; }
        lock(_lockObject) {
            _products = DAL.LoadProducts()
        }
        return products;
    }
}

我更喜欢这种模式的原因是,System.Runtime.Caching.MemoryCache是​​因为它不使用序列化,因此可以扩展到大对象;我已经成功地使用它来从整个数据库表中缓存非常大的对象集合,然后我使用LINQ查询而不是使用SQL查询数据库,从而大大提高了性能。这种模式在以下场景中的许多项目中都很有用:

  1. 我想缓存从存储中检索昂贵的大型数据集
  2. 数据将缓存数小时或数天,并且不会影响陈旧性。
  3. 数据经常使用,但通常会针对特定请求进行唯一过滤或转换。
  4. 数据量很容易在主机服务器的内存容量范围内。
  5. 由于我发现这种模式非常有用,我很好奇为什么关于这个主题的各种书籍和教程甚至都没有真正讨论它作为一种选择。

2 个答案:

答案 0 :(得分:1)

鉴于您对MemoryCache的理解是错误的,并且在MemoryCache中存储内容比使用静态内容更少的代码,我不明白为什么您会坚持使用容易出错,漏洞的模式,并且更难以使用...

无论如何,有时使用静态来缓存某些东西是合适的。但是,一般来说,您应该初始化静态并且在过程的生命周期中永远不会更改静态。一旦你开始玩东西,你就会开始痛苦。

答案 1 :(得分:1)

这是一个旧线程,但是遇到一些未填充的数据缓存时,有两个线程执行相同工作的问题有一个简单的解决方案。该技术称为双重锁定。

public static class Repository<T>
{
    private static readonly object LockSemaphore = new object();
    private static T _dataYouWantCached;

    public static void ReadData()
    {
        if (_dataYouWantCached != null)
        {
            return _dataYouWantCached;
        }

        lock (LockSemaphore)
        {
            //This second check will prevent the "next" thread from requerying the same data that
            //the first thread populated.
            //This is the "Double Lock"
            if (_dataYouWantCached != null)
                return _dataYouWantCached;

            _dataYouWantCached = SomeStaticDataAccess.LoadData();

            return _dataYouWantCached;
        }   
    }
}