ASP.NET MVC应用程序中应该在哪里进行缓存?

时间:2008-10-24 20:27:44

标签: asp.net-mvc caching

我需要使用 System.Web.Caching.Cache 缓存一些数据。不确定它是否重要,但数据不是来自数据库,而是来自过多的自定义对象。

ASP.NET MVC对我来说是一个新手,我想知道这个缓存发生在哪里是有意义的?

型号或控制器?

在某种程度上,在模型级别缓存是有意义的,但我不一定知道这样做的含义(如果有的话)。如果要在控制器级别进行缓存,是否会影响所有请求,还是只影响当前的 HttpContext

那么......应该在何处完成应用程序数据缓存,以及实际执行此操作的好方法是什么?

更新

感谢您的答案!我仍然试图收集在给定不同场景的情况下缓存最有意义的地方。如果一个人正在缓存整个页面,那么将它保留在视图中是有道理的,但是当它不是整个页面时在哪里画线?

6 个答案:

答案 0 :(得分:7)

我认为它最终取决于你正在缓存的 。如果要缓存渲染页面的结果,那么它与请求的Http特性紧密相关,并建议使用ActionFilter级别的缓存机制。

另一方面,如果要缓存驱动页面本身的数据,则应考虑模型级缓存。在这种情况下,控制器不关心何时生成数据,它只是对数据执行逻辑操作并准备查看。模型级缓存的另一个参数是,如果您对附加到Http上下文的模型数据有其他依赖性。

例如,我有一个网络应用程序,我的大多数模型被抽象成一个完全不同的项目。这是因为会有第二个使用相同支持的网络应用程序,并且我们有可能使用相同数据的非基于Web的应用程序。我的大部分数据来自网络服务,这可能是性能杀手,所以我有模型级缓存,控制器和视图完全不知道。

答案 1 :(得分:3)

我不知道你问题的答案,但是Jeff Atwood谈到了SO团队如何使用最新的hanselminutes节目使用stackoverflow.com的MVC框架进行缓存,这可能对你有所帮助:

http://www.hanselminutes.com/default.aspx?showID=152

答案 2 :(得分:3)

快速回答

我将从 CONTROLLER 缓存开始,使用OutputCache属性,然后根据需要添加模型缓存。它实施起来更快,并且具有即时结果。

详细答案(因为我喜欢我的声音)

这是一个例子。

[OutputCache(Duration=60, VaryByParam="None")]
public ActionResult CacheDemo() {
  return View();
}

这意味着如果用户访问该站点(针对属性中定义的缓存要求),则完成工作的工作量会减少。如果只有模型缓存,那么即使逻辑(并且很可能是数据库命中)被缓存,Web服务器仍然必须呈现页面。为什么渲染结果总是一样?

首先从OutputCach开始,然后在对网站进行性能测试时转移到模型缓存。

输出缓存开始时也简单得多。您不必担心Web场分布式缓存probs(如果您是服务器场的一部分)和模型的缓存提供程序。

高级缓存技术

您还可以申请甜甜圈缓存 - >仅缓存UI页面的一部分:) Check it out

答案 3 :(得分:2)

我会选择模型级别的缓存。 (一般来说,建议似乎是在控制器级别最小化业务逻辑 并尽可能多地移动到模型类中。)

这样做怎么样:

我在类Entry所代表的模型中有一些条目 和条目来源(来自数据库,或'过多的自定义对象')。 在模型中,我创建了一个用于检索条目的界面:

public interface IEntryHandler
{
    IEnumerable<Entry> GetEntries();
}

在模型中我有IEntryHandler的实际实现 条目从缓存中读取并写入缓存。

public class EntryHandler : IEntryHandler
{
    public IEnumerable<Entry> GetEntries()
    {
        // Check if the objects are in the cache:
        List<Entry> entries = [Get entries from cache]
        if (entries == null)
        {
            // There were no entries in the cache, so we read them from the source:
            entries = [Get entries from database or 'plethora of custom objects']
            [Save the retrieved entries to cache for later use]
        }
        return entries;
    }
}

然后控制器会调用IEntryHandler

public class HomeController : Controller
{
    private IEntryHandler _entryHandler;

    // The default constructor, using cache and database/custom objects
    public HomeController()
        : this(new EntryHandler())
    {
    }

    // This constructor allows us to unit test the controller 
    // by writing a test class that implements IEntryHandler
    // but does not affect cache or entries in the database/custom objects
    public HomeController(IEntryHandler entryHandler)
    {
        _entryHandler = entryHandler;
    }

    // This controller action returns a list of entries to the view:
    public ActionResult Index()
    {
        return View(_entryHandler.GetEntries());
    }
}

这样就可以在不触及真正的缓存/数据库/自定义对象的情况下对控制器进行单元测试。

答案 4 :(得分:1)

我认为缓存应该以某种方式与模型相关。我认为控制器不应该更关心数据。控制器的职责是将数据 - 无论它来自何处 - 映射到视图。

还要考虑为什么需要缓存?你想保存处理,数据传输还是什么?这将帮助您了解获取缓存层所需的具体位置。

答案 5 :(得分:1)

这完全取决于操作的成本。如果您有复杂的查询,那么在控制器级别缓存数据可能是有意义的,这样查询就不会再次执行(直到缓存过期)。

请记住,缓存是一个非常复杂的主题。您可以在缓存中存储许多不同的地方:

  • Akamai / CDN缓存
  • 浏览器缓存
  • 内存中应用程序缓存
  • .NET的缓存对象
  • Page指令
  • 分布式缓存(memcached)