我使用Asp.net mvc 4(c#)构建自己的cms,我想缓存一些数据库数据,如:本地化,搜索类别(它的长尾,每个类别都有自己的子和子子类别) )等等。
一直查询数据库会有点过分,因为每个页面请求可能超过30-100个查询,但用户很少更新这些数据库
那么最好的方法(性能和便利性)是什么?
我知道如何使用动作的OutputCache,但这不是我在这种情况下需要的,它是缓存html,但我需要的是,例如,我自己的助手@html.Localization("Newsletter.Tite")
将取值语言,或与数据等交互的任何其他帮助者。
我认为(不太确定)我需要缓存我想要的数据,只有在第一次调用应用程序时,然后使用缓存位置,但我甚至没有任何经验它
答案 0 :(得分:32)
我必须缓存常见的数据库数据,例如下拉列表中显示的数据。我用了MemoryCache
。我使用Entity Framework code first
和Autofac
进行依赖注入。
以下是我在解决方案中所做的一部分,可能不适合你,但它对我有用,虽然不完美但需要大量的清理工作。
我的ICacheManager
界面:
public interface ICacheManager
{
T Get<T>(string key);
void Set(string key, object data, int cacheTime);
bool IsSet(string key);
void Remove(string key);
void Clear();
}
我的CacheManager
课程:
public class CacheManager : ICacheManager
{
private ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
public T Get<T>(string key)
{
return (T)Cache[key];
}
public void Set(string key, object data, int cacheTime)
{
if (data == null)
{
return;
}
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
public bool IsSet(string key)
{
return (Cache.Contains(key));
}
public void Remove(string key)
{
Cache.Remove(key);
}
public void Clear()
{
foreach (var item in Cache)
{
Remove(item.Key);
}
}
}
我的缓存的扩展类:
public static class CacheExtensions
{
public static T Get<T>(this ICacheManager cacheManager, string key, Func<T> acquire)
{
return Get(cacheManager, key, 60, acquire);
}
public static T Get<T>(this ICacheManager cacheManager, string key, int cacheTime, Func<T> acquire)
{
if (cacheManager.IsSet(key))
{
return cacheManager.Get<T>(key);
}
else
{
var result = acquire();
cacheManager.Set(key, result, cacheTime);
return result;
}
}
}
这就是我在我的存储库类中使用它的方法。此方法返回所有银行的列表,该列表显示在下拉列表中。
public class BankRepository : RepositoryBase<Bank>, IBankRepository
{
private readonly ICacheManager cacheManager;
private const string BanksAllCacheKey = "banks-all";
public BankRepository(IDatabaseFactory databaseFactory, ICacheManager cacheManager)
: base(databaseFactory)
{
Check.Argument.IsNotNull(cacheManager, "cacheManager");
this.cacheManager = cacheManager;
}
public IEnumerable<Bank> FindAll()
{
string key = string.Format(BanksAllCacheKey);
return cacheManager.Get(key, () =>
{
var query = from bank in DatabaseContext.Banks
orderby bank.Name
select bank;
return query.ToList();
});
}
}
我希望这会有所帮助。这是一个非常简单的实现,但它适用于我。有很多关于如何在ASP.NET MVC
中使用缓存策略的文章。只需Google
。
答案 1 :(得分:31)
您可以使用内置MemoryCache
来存储从数据库中检索到的整个结果集。
典型模式:
MyModel model = MemoryCache.Default["my_model_key"] as MyModel;
if (model == null)
{
model = GetModelFromDatabase();
MemoryCache.Default["my_model_key"] = model;
}
// you could use the model here
答案 2 :(得分:4)
在选择缓存实现之前,有几点需要考虑,但您必须决定的主要事项之一是您希望缓存发生在什么时候 - 数据访问,模型创建或UI生成?其中一个或所有地方?
您有多种选择,但对于常规数据缓存,您可以使用System.Runtime.Caching.MemoryCache
,或者对于更灵活和更有价值的内容,您可以查看使用NoSQL的实现,例如Redis。
您可以使用MemoryCache
进行数据缓存,但可以使用Redis缓存构成视图模型的聚合。如果您使用Redis,您当然可以使用此处理所有缓存。好处是所有数据在应用程序重新启动时都会保持不变。缺点是它成为运行CMS的额外要求。
要考虑的其他因素是一致性(使用一些IoC会有所帮助)并允许数据在更新后无效。因此,有一些更新缓存的方法。
关于最佳方法,在您的情况下,如果您要创建新的CMS应用程序,请从小/简单开始并逐步构建。你可能不会在第一时间得到完美,但只要你在你的方法中保持一致和清晰,就应该很容易建立在你所做的事情上,或者换掉并尝试不同/更好的事情。