使用HttpRuntime.Cache发布问题

时间:2009-06-22 23:00:15

标签: c# asp.net caching

使用以下.net代码将对象添加到缓存中:

public static void Add<T>(string key, T dataToCache)
{
    try
    {
        ApplicationLog.Instance.WriteInfoFormat("Inserting item with key {0} into Cache...", key);

        HttpRuntime.Cache.Insert(
            key,
            dataToCache,
            null,
            DateTime.Now.AddDays(7),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

    catch (Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);             
    }
}

这是我从缓存中检索值的代码:

public static T Get<T>(string key) 
{   
    try
    {                
        if (Exists(key))
        {
            ApplicationLog.Instance.WriteInfoFormat("Retrieving item with key {0} from Cache...", key);

            return (T)HttpRuntime.Cache[key];
        }
        else
        {
            ApplicationLog.Instance.WriteInfoFormat("Item with key {0} does not exist in Cache.", key);
            return default(T); 
        }
    }
    catch(Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);
        return default(T); 
    }
}


public static bool Exists(string key)
{
    bool retVal = false;
    try
    {
        retVal= HttpRuntime.Cache[key] != null;
    }
    catch (Exception ex)
    {
        ApplicationLog.Instance.WriteException(ex);
    }
    return retVal; 
}

但我发现每隔2分钟左右,缓存的对象值就会设置为null,从而再次从数据库中提取该值。

我在这里缺少什么?

3 个答案:

答案 0 :(得分:7)

首先,您的访问权限未同步,因此这是一个很好的问题来源。从HttpRuntime Cache读取保证是线程安全的,所以你应该真正尝试阅读你的项目作为每个缓存操作的第一步。

在检查是否Exists和实际检索项目之间可能发生很多事情(例如您的项目不再在那里)。你应该得到你正在寻找的项目的句柄,如果不是,那么通过从持久性数据存储中提取它来提供线程安全的插入。

因此,如果数据不存在,您的Add逻辑将进入Get。提供单独的Add逻辑没有任何根本错误,与阻止对特定数据的进一步请求相比,您应该多次测量数据库的成本。

T GetT(string key)
{
    T item = (cache.Get(key) as T);
    if (item == null)
    {
        lock (yourSyncRoot)
        {
            // double check it here
            item = (cache.Get(key) as T);
            if (item != null)
                return item;

            item = GetMyItemFromMyPersistentStore(key); // db?
            if (item == null)
                return null;

            string[] dependencyKeys = {your, dependency, keys};

            cache.Insert(key, item, new CacheDependency(null, dependencyKeys), 
                         absoluteExpiration, slidingExpiration, priority, null);
        }
    }
    return item;
}

根据您的到期政策,您可以将数据存储在内存中并快速提供。同步访问它,但正如我所说,测量它并根据您的需要进行调整。在更新项目并将其正确保存到持久性商店后的业务逻辑中,只需将其从缓存中删除,然后对Get的下一次调用将再次获取它。

答案 1 :(得分:6)

当您说每两分钟插入的值设置为null时,这是否意味着您感兴趣的项目或缓存中的每个项目?

我问这个,因为只要应用程序正在运行,缓存就会存在。如果重新启动应用程序,缓存就会消失。这可以解释如果每2分钟一切都消失的行为。在这种情况下,你手上有一个不同的问题:为什么应用程序每2分钟重新启动一次。

如果它只是一些项目,那么它可能是一个内存问题。缓存会自行清理以响应内存不足。我相信有一种方法可以为插入的值设置优先级。但是当你内存不足时,这应该只是一个问题。

如果仍然无法解决您的问题,可以通过某种方式了解删除项目的原因。它解释为here

答案 2 :(得分:2)

可能是因为内存不足,缓存会在内存不足时自动终止缓存中的项目。如果要清除一个项目,可以使用可选参数设置缓存中项目的优先级在另一个之前。