rba*_*all 51 asp.net-mvc caching
我想在ASP.NET MVC中缓存对象.我有一个BaseController我希望所有控制器继承自己的东西.在BaseController中有一个User属性,它将简单地从数据库中获取用户数据,以便我可以在控制器中使用它,或将其传递给视图.
我想缓存这些信息.我在每个页面上都使用此信息,因此无需每个页面请求转到数据库.
我喜欢这样的东西:
if(_user is null)
GrabFromDatabase
StuffIntoCache
return CachedObject as User
Run Code Online (Sandbox Code Playgroud)
如何在ASP.NET MVC中实现简单缓存?
小智 71
您仍然可以使用缓存(在所有响应中共享)和会话(每个用户唯一)进行存储.
我喜欢以下"尝试从缓存/创建和存储"模式(c#-like伪代码):
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;
}
}
Run Code Online (Sandbox Code Playgroud)
你会这样使用它:
var user = HttpRuntime
.Cache
.GetOrStore<User>(
$"User{_userId}",
() => Repository.GetUser(_userId));
Run Code Online (Sandbox Code Playgroud)
您可以将此模式调整为Session,ViewState(ugh)或任何其他缓存机制.您还可以扩展ControllerContext.HttpContext(我认为它是System.Web.Extensions中的包装器之一),或者创建一个新类来实现它,并为模拟缓存提供了一些空间.
nja*_*boy 59
我把威尔的答案,并修改了它,使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;
}
}
Run Code Online (Sandbox Code Playgroud)
我还考虑进一步实现一个可测试的Session解决方案,该解决方案扩展了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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您希望缓存请求的长度,请将其放在控制器基类中:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果要缓存更长时间,请使用将ControllerContext调用替换为Cache [].如果您确实选择使用Cache对象进行更长时间的缓存,则需要使用唯一的缓存密钥,因为它将在请求/用户之间共享.
这里的其他几个答案不涉及以下内容:
这可能导致生成器(可能需要很长时间)在不同线程中运行不止一次。
这是我的版本,不应该遇到这个问题:
// using System;
// using System.Web.Caching;
// /sf/answers/2971040621/
// Usage: HttpRuntime.Cache.GetOrStore("myKey", () => GetSomethingToCache());
public static class CacheExtensions
{
private static readonly object sync = new object();
private static TimeSpan defaultExpire = TimeSpan.FromMinutes(20);
public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator) =>
cache.GetOrStore(key, generator, defaultExpire);
public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator, TimeSpan expire)
{
var result = cache[key];
if (result == null)
{
lock (sync)
{
result = cache[key];
if (result == null)
{
result = generator();
cache.Insert(key, result, null, DateTime.UtcNow.AddMinutes(expire.TotalMinutes), Cache.NoSlidingExpiration);
}
}
}
return (T)result;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36656 次 |
| 最近记录: |