我想在ASP.NET MVC中缓存对象.我有一个BaseController
我希望所有控制器继承自己的东西.在BaseController中有一个User
属性,它将简单地从数据库中获取用户数据,以便我可以在控制器中使用它,或将其传递给视图.
我想缓存这些信息.我在每个页面上都使用此信息,因此无需每个页面请求转到数据库.
我喜欢这样的东西:
if(_user is null) GrabFromDatabase StuffIntoCache return CachedObject as User
如何在ASP.NET MVC中实现简单缓存?
您仍然可以使用缓存(在所有响应中共享)和会话(每个用户唯一)进行存储.
我喜欢以下"尝试从缓存/创建和存储"模式(c#-like伪代码):
public static class CacheExtensions { public static T GetOrStore(this Cache cache, string key, Func generator) { var result = cache[key]; if(result == null) { result = generator(); cache[key] = result; } return (T)result; } }
你会这样使用它:
var user = HttpRuntime .Cache .GetOrStore( $"User{_userId}", () => Repository.GetUser(_userId));
您可以将此模式调整为Session,ViewState(ugh)或任何其他缓存机制.您还可以扩展ControllerContext.HttpContext(我认为它是System.Web.Extensions中的包装器之一),或者创建一个新类来实现它,并为模拟缓存提供了一些空间.
我把威尔的答案,并修改了它,使CacheExtensions
类的静态和为了应对的可能性,建议有轻微改动Func
之中null
:
public static class CacheExtensions { private static object sync = new object(); public const int DefaultCacheExpiration = 20; ////// Allows Caching of typed data /// ///( /// string.Format("User{0}", _userId), /// () => Repository.GetUser(_userId)); /// /// ]]> ////// calling object /// Cache key /// Func that returns the object to store in cache /// /// Uses a default cache expiration period as defined in public static T GetOrStore( this Cache cache, string key, Func generator ) { return cache.GetOrStore( key, (cache[key] == null && generator != null) ? generator() : default( T ), DefaultCacheExpiration ); } /// /// Allows Caching of typed data /// ///( /// string.Format("User{0}", _userId), /// () => Repository.GetUser(_userId)); /// /// ]]> ////// calling object /// Cache key /// Func that returns the object to store in cache /// Time to expire cache in minutes /// public static T GetOrStore ( this Cache cache, string key, Func generator, double expireInMinutes ) { return cache.GetOrStore( key, (cache[key] == null && generator != null) ? generator() : default( T ), expireInMinutes ); } /// /// Allows Caching of typed data /// ///( /// string.Format("User{0}", _userId),_userId)); /// /// ]]> ////// calling object /// Cache key /// Object to store in cache /// /// Uses a default cache expiration period as defined in public static T GetOrStore( this Cache cache, string key, T obj ) { return cache.GetOrStore( key, obj, DefaultCacheExpiration ); } /// /// Allows Caching of typed data /// ///( /// string.Format("User{0}", _userId), /// () => Repository.GetUser(_userId)); /// /// ]]> ////// calling object /// Cache key /// Object to store in cache /// Time to expire cache in minutes /// public static T GetOrStore ( 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; } }
我还考虑进一步实现一个可测试的Session解决方案,该解决方案扩展了System.Web.HttpSessionStateBase抽象类.
public static class SessionExtension { ////// /// ///( /// string.Format("User{0}", _userId), /// () => Repository.GetUser(_userId)); /// /// ]]> ////// /// /// /// public static T GetOrStore ( this HttpSessionStateBase session, string name, Func generator ) { var result = session[name]; if ( result != null ) return (T)result; result = generator != null ? generator() : default( T ); session.Add( name, result ); return (T)result; } }
如果您希望缓存请求的长度,请将其放在控制器基类中:
public User User { get { User _user = ControllerContext.HttpContext.Items["user"] as User; if (_user == null) { _user = _repository.Get(id); ControllerContext.HttpContext.Items["user"] = _user; } return _user; } }
如果要缓存更长时间,请使用将ControllerContext调用替换为Cache [].如果您确实选择使用Cache对象进行更长时间的缓存,则需要使用唯一的缓存密钥,因为它将在请求/用户之间共享.