我想在ASP.NET MVC中缓存对象。我有一个希望所有控制器都继承的BaseController。在BaseController中有一个User属性,它将简单地从数据库中获取用户数据,以便我可以在控制器中使用它,或者将它传递给视图。
我想缓存这个信息。我在每个页面上都使用这些信息,所以没有必要在每个页面请求时都访问数据库。
我想要这样的东西:
if(_user is null)
GrabFromDatabase
StuffIntoCache
return CachedObject as User如何在ASP.NET MVC中实现简单的缓存?
发布于 2009-01-15 01:20:30
您仍然可以使用缓存(在所有响应中共享)和会话(每个用户唯一)进行存储。
我喜欢下面的"try get from cache/create and store“模式(类似于c#的伪代码):
public static class CacheExtensions
{
public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator)
{
var result = cache[key];
if(result == null)
{
result = generator();
cache[key] = result;
}
return (T)result;
}
}你可以这样使用它:
var user = HttpRuntime
.Cache
.GetOrStore<User>(
$"User{_userId}",
() => Repository.GetUser(_userId));您可以将此模式调整为会话、ViewState (ugh)或任何其他缓存机制。您还可以扩展ControllerContext.HttpContext (我认为它是System.Web.Extensions中的包装器之一),或者创建一个新类来做这件事,为模拟缓存留出一些空间。
发布于 2009-06-09 08:35:27
我接受了Will的回答,并对其进行了修改,使CacheExtensions类成为静态类,并建议稍作修改,以处理Func<T>为null的可能性:
public static class CacheExtensions
{
private static object sync = new object();
public const int DefaultCacheExpiration = 20;
/// <summary>
/// Allows Caching of typed data
/// </summary>
/// <example><![CDATA[
/// var user = HttpRuntime
/// .Cache
/// .GetOrStore<User>(
/// string.Format("User{0}", _userId),
/// () => Repository.GetUser(_userId));
///
/// ]]></example>
/// <typeparam name="T"></typeparam>
/// <param name="cache">calling object</param>
/// <param name="key">Cache key</param>
/// <param name="generator">Func that returns the object to store in cache</param>
/// <returns></returns>
/// <remarks>Uses a default cache expiration period as defined in <see cref="CacheExtensions.DefaultCacheExpiration"/></remarks>
public static T GetOrStore<T>( this Cache cache, string key, Func<T> generator ) {
return cache.GetOrStore( key, (cache[key] == null && generator != null) ? generator() : default( T ), DefaultCacheExpiration );
}
/// <summary>
/// Allows Caching of typed data
/// </summary>
/// <example><![CDATA[
/// var user = HttpRuntime
/// .Cache
/// .GetOrStore<User>(
/// string.Format("User{0}", _userId),
/// () => Repository.GetUser(_userId));
///
/// ]]></example>
/// <typeparam name="T"></typeparam>
/// <param name="cache">calling object</param>
/// <param name="key">Cache key</param>
/// <param name="generator">Func that returns the object to store in cache</param>
/// <param name="expireInMinutes">Time to expire cache in minutes</param>
/// <returns></returns>
public static T GetOrStore<T>( this Cache cache, string key, Func<T> generator, double expireInMinutes ) {
return cache.GetOrStore( key, (cache[key] == null && generator != null) ? generator() : default( T ), expireInMinutes );
}
/// <summary>
/// Allows Caching of typed data
/// </summary>
/// <example><![CDATA[
/// var user = HttpRuntime
/// .Cache
/// .GetOrStore<User>(
/// string.Format("User{0}", _userId),_userId));
///
/// ]]></example>
/// <typeparam name="T"></typeparam>
/// <param name="cache">calling object</param>
/// <param name="key">Cache key</param>
/// <param name="obj">Object to store in cache</param>
/// <returns></returns>
/// <remarks>Uses a default cache expiration period as defined in <see cref="CacheExtensions.DefaultCacheExpiration"/></remarks>
public static T GetOrStore<T>( this Cache cache, string key, T obj ) {
return cache.GetOrStore( key, obj, DefaultCacheExpiration );
}
/// <summary>
/// Allows Caching of typed data
/// </summary>
/// <example><![CDATA[
/// var user = HttpRuntime
/// .Cache
/// .GetOrStore<User>(
/// string.Format("User{0}", _userId),
/// () => Repository.GetUser(_userId));
///
/// ]]></example>
/// <typeparam name="T"></typeparam>
/// <param name="cache">calling object</param>
/// <param name="key">Cache key</param>
/// <param name="obj">Object to store in cache</param>
/// <param name="expireInMinutes">Time to expire cache in minutes</param>
/// <returns></returns>
public static T GetOrStore<T>( this Cache cache, string key, T obj, double expireInMinutes ) {
var result = cache[key];
if ( result == null ) {
lock ( sync ) {
result = cache[key];
if ( result == null ) {
result = obj != null ? obj : default( T );
cache.Insert( key, result, null, DateTime.Now.AddMinutes( expireInMinutes ), Cache.NoSlidingExpiration );
}
}
}
return (T)result;
}
}我还会考虑进一步实现一个扩展System.Web.HttpSessionStateBase抽象类的可测试会话解决方案。
public static class SessionExtension
{
/// <summary>
///
/// </summary>
/// <example><![CDATA[
/// var user = HttpContext
/// .Session
/// .GetOrStore<User>(
/// string.Format("User{0}", _userId),
/// () => Repository.GetUser(_userId));
///
/// ]]></example>
/// <typeparam name="T"></typeparam>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="generator"></param>
/// <returns></returns>
public static T GetOrStore<T>( this HttpSessionStateBase session, string name, Func<T> generator ) {
var result = session[name];
if ( result != null )
return (T)result;
result = generator != null ? generator() : default( T );
session.Add( name, result );
return (T)result;
}
}发布于 2009-01-14 23:11:25
如果你想把它缓存到请求的长度,把这个放到你的控制器基类中:
public User User {
get {
User _user = ControllerContext.HttpContext.Items["user"] as User;
if (_user == null) {
_user = _repository.Get<User>(id);
ControllerContext.HttpContext.Items["user"] = _user;
}
return _user;
}
}如果希望缓存更长时间,请使用对Cache[]的调用替换ControllerContext调用。如果您确实选择使用Cache对象来缓存更长时间,则需要使用唯一的缓存键,因为它将在请求/用户之间共享。
https://stackoverflow.com/questions/445050
复制相似问题