我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。

在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。

谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。

我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。


当前回答

我参考了TT的帖子,并建议以下方法:

参考系统。并使用System.Web.Caching.Cache

public string[] GetNames()
{ 
    var noms = Cache["names"];
    if(noms == null) 
    {    
        noms = DB.GetNames();
        Cache["names"] = noms; 
    }

    return ((string[])noms);
}

您不应该返回从缓存中重新读取的值,因为您永远不知道在特定时刻它是否仍在缓存中。即使您之前将它插入到语句中,它可能已经消失或从未添加到缓存中—您只是不知道。

因此,添加从数据库读取的数据并直接返回,而不是从缓存中重新读取。

其他回答

下面是我使用的一个漂亮而简单的缓存助手类/服务:

using System.Runtime.Caching;  

public class InMemoryCache: ICacheService
{
    public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
    {
        T item = MemoryCache.Default.Get(cacheKey) as T;
        if (item == null)
        {
            item = getItemCallback();
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(10));
        }
        return item;
    }
}

interface ICacheService
{
    T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}

用法:

cacheProvider.GetOrSet("cache key", (delegate method if cache is empty));

缓存提供程序将检查缓存中是否有名称为“缓存id”的东西,如果没有,它将调用委托方法来获取数据并将其存储在缓存中。

例子:

var products=cacheService.GetOrSet("catalog.products", ()=>productRepository.GetAll())

我参考了TT的帖子,并建议以下方法:

参考系统。并使用System.Web.Caching.Cache

public string[] GetNames()
{ 
    var noms = Cache["names"];
    if(noms == null) 
    {    
        noms = DB.GetNames();
        Cache["names"] = noms; 
    }

    return ((string[])noms);
}

您不应该返回从缓存中重新读取的值,因为您永远不知道在特定时刻它是否仍在缓存中。即使您之前将它插入到语句中,它可能已经消失或从未添加到缓存中—您只是不知道。

因此,添加从数据库读取的数据并直接返回,而不是从缓存中重新读取。

Steve Smith写了两篇很棒的博文,演示了如何在ASP中使用他的CachedRepository模式。净MVC。它有效地使用存储库模式,并允许您在无需更改现有代码的情况下获得缓存。

http://ardalis.com/Introducing-the-CachedRepository-Pattern

http://ardalis.com/building-a-cachedrepository-via-strategy-pattern

在这两篇文章中,他向你展示了如何建立这种模式,并解释了为什么它是有用的。通过使用这种模式,您可以在现有代码看不到任何缓存逻辑的情况下获得缓存。本质上,使用缓存的存储库就像使用其他存储库一样。

我使用两个类。第一个是缓存核心对象:

public class Cacher<TValue>
    where TValue : class
{
    #region Properties
    private Func<TValue> _init;
    public string Key { get; private set; }
    public TValue Value
    {
        get
        {
            var item = HttpRuntime.Cache.Get(Key) as TValue;
            if (item == null)
            {
                item = _init();
                HttpContext.Current.Cache.Insert(Key, item);
            }
            return item;
        }
    }
    #endregion

    #region Constructor
    public Cacher(string key, Func<TValue> init)
    {
        Key = key;
        _init = init;
    }
    #endregion

    #region Methods
    public void Refresh()
    {
        HttpRuntime.Cache.Remove(Key);
    }
    #endregion
}

第二个是缓存对象列表:

public static class Caches
{
    static Caches()
    {
        Languages = new Cacher<IEnumerable<Language>>("Languages", () =>
                                                          {
                                                              using (var context = new WordsContext())
                                                              {
                                                                  return context.Languages.ToList();
                                                              }
                                                          });
    }
    public static Cacher<IEnumerable<Language>> Languages { get; private set; }
}

我要说的是,如果您发现以前的解决方案非常复杂,那么在这个持久化数据问题上实现Singleton可以是一个解决方案

 public class GPDataDictionary
{
    private Dictionary<string, object> configDictionary = new Dictionary<string, object>();

    /// <summary>
    /// Configuration values dictionary
    /// </summary>
    public Dictionary<string, object> ConfigDictionary
    {
        get { return configDictionary; }
    }

    private static GPDataDictionary instance;
    public static GPDataDictionary Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new GPDataDictionary();
            }
            return instance;
        }
    }

    // private constructor
    private GPDataDictionary() { }

}  // singleton