当前位置:  开发笔记 > 编程语言 > 正文

如何在ASP.NET MVC中缓存对象?

如何解决《如何在ASP.NETMVC中缓存对象?》经验,为你挑选了3个好方法。

我想在ASP.NET MVC中缓存对象.我有一个BaseController我希望所有控制器继承自己的东西.在BaseController中有一个User属性,它将简单地从数据库中获取用户数据,以便我可以在控制器中使用它,或将其传递给视图.

我想缓存这些信息.我在每个页面上都使用此信息,因此无需每个页面请求转到数据库.

我喜欢这样的东西:

if(_user is null)
  GrabFromDatabase
  StuffIntoCache
return CachedObject as User

如何在ASP.NET MVC中实现简单缓存?



1> 小智..:

您仍然可以使用缓存(在所有响应中共享)和会话(每个用户唯一)进行存储.

我喜欢以下"尝试从缓存/创建和存储"模式(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中的包装器之一),或者创建一个新类来实现它,并为模拟缓存提供了一些空间.


不要使用cache [key] = result而是使用Cache.Insert(...),因为你可以在Insert中放置依赖项,过期策略等.

2> njappboy..:

我把威尔的答案,并修改了它,使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;
    }

}


我认为您的代码中存在错误.即使缓存存在,也会调用该函数.将`generator!= null`改为`(cache [key] == null && generator!= null)`来修复bug.

3> John Sheehan..:

如果您希望缓存请求的长度,请将其放在控制器基类中:

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对象进行更长时间的缓存,则需要使用唯一的缓存密钥,因为它将在请求/用户之间共享.


已经有一段时间了,您回家了吗?:)
推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有