我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。
在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。
谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。
我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。
我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。
在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。
谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。
我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。
当前回答
参考系统。并使用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特定的,我一直使用这种方法缓存数据。
其他回答
你也可以尝试使用内置在ASP MVC中的缓存:
添加以下属性到你想要缓存的控制器方法:
[OutputCache(Duration=10)]
在这种情况下,ActionResult将被缓存10秒。
更多信息请点击这里
下面是我使用的一个漂亮而简单的缓存助手类/服务:
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())
参考系统。并使用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特定的,我一直使用这种方法缓存数据。
我要说的是,如果您发现以前的解决方案非常复杂,那么在这个持久化数据问题上实现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
下面是对Hrvoje Hudo的回答的改进。这个实现有几个关键的改进:
缓存键是根据更新数据的函数和传入的指定依赖关系的对象自动创建的 为任何缓存持续时间传递时间跨度 使用锁来保证线程安全
注意,这依赖于Newtonsoft。Json来序列化dependsOn对象,但是可以很容易地将其替换为任何其他序列化方法。
ICache.cs
public interface ICache
{
T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class;
}
InMemoryCache.cs
using System;
using System.Reflection;
using System.Runtime.Caching;
using Newtonsoft.Json;
public class InMemoryCache : ICache
{
private static readonly object CacheLockObject = new object();
public T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class
{
string cacheKey = GetCacheKey(getItemCallback, dependsOn);
T item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
lock (CacheLockObject)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.Add(duration));
}
}
return item;
}
private string GetCacheKey<T>(Func<T> itemCallback, object dependsOn) where T: class
{
var serializedDependants = JsonConvert.SerializeObject(dependsOn);
var methodType = itemCallback.GetType();
return methodType.FullName + serializedDependants;
}
}
用法:
var order = _cache.GetOrSet(
() => _session.Set<Order>().SingleOrDefault(o => o.Id == orderId)
, new { id = orderId }
, new TimeSpan(0, 10, 0)
);