我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。
在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。
谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。
我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。
我已经阅读了大量关于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);
}
您不应该返回从缓存中重新读取的值,因为您永远不知道在特定时刻它是否仍在缓存中。即使您之前将它插入到语句中,它可能已经消失或从未添加到缓存中—您只是不知道。
因此,添加从数据库读取的数据并直接返回,而不是从缓存中重新读取。
其他回答
参考系统。并使用System.Web.Caching.Cache
public string[] GetNames()
{
string[] names = Cache["names"] as string[];
if(names == null) //not in cache
{
names = DB.GetNames();
Cache["names"] = names;
}
return names;
}
有点简化了,但我想应该可以。这不是MVC特定的,我一直使用这种方法缓存数据。
public sealed class CacheManager
{
private static volatile CacheManager instance;
private static object syncRoot = new Object();
private ObjectCache cache = null;
private CacheItemPolicy defaultCacheItemPolicy = null;
private CacheEntryRemovedCallback callback = null;
private bool allowCache = true;
private CacheManager()
{
cache = MemoryCache.Default;
callback = new CacheEntryRemovedCallback(this.CachedItemRemovedCallback);
defaultCacheItemPolicy = new CacheItemPolicy();
defaultCacheItemPolicy.AbsoluteExpiration = DateTime.Now.AddHours(1.0);
defaultCacheItemPolicy.RemovedCallback = callback;
allowCache = StringUtils.Str2Bool(ConfigurationManager.AppSettings["AllowCache"]); ;
}
public static CacheManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new CacheManager();
}
}
}
return instance;
}
}
public IEnumerable GetCache(String Key)
{
if (Key == null || !allowCache)
{
return null;
}
try
{
String Key_ = Key;
if (cache.Contains(Key_))
{
return (IEnumerable)cache.Get(Key_);
}
else
{
return null;
}
}
catch (Exception)
{
return null;
}
}
public void ClearCache(string key)
{
AddCache(key, null);
}
public bool AddCache(String Key, IEnumerable data, CacheItemPolicy cacheItemPolicy = null)
{
if (!allowCache) return true;
try
{
if (Key == null)
{
return false;
}
if (cacheItemPolicy == null)
{
cacheItemPolicy = defaultCacheItemPolicy;
}
String Key_ = Key;
lock (Key_)
{
return cache.Add(Key_, data, cacheItemPolicy);
}
}
catch (Exception)
{
return false;
}
}
private void CachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), " | Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ", arguments.CacheItem.Value.ToString());
LogManager.Instance.Info(strLog);
}
}
下面是我使用的一个漂亮而简单的缓存助手类/服务:
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())
你也可以尝试使用内置在ASP MVC中的缓存:
添加以下属性到你想要缓存的控制器方法:
[OutputCache(Duration=10)]
在这种情况下,ActionResult将被缓存10秒。
更多信息请点击这里
我参考了TT的帖子,并建议以下方法:
参考系统。并使用System.Web.Caching.Cache
public string[] GetNames()
{
var noms = Cache["names"];
if(noms == null)
{
noms = DB.GetNames();
Cache["names"] = noms;
}
return ((string[])noms);
}
您不应该返回从缓存中重新读取的值,因为您永远不知道在特定时刻它是否仍在缓存中。即使您之前将它插入到语句中,它可能已经消失或从未添加到缓存中—您只是不知道。
因此,添加从数据库读取的数据并直接返回,而不是从缓存中重新读取。