qué - ¿Dónde debe ocurrir el almacenamiento en caché en una aplicación ASP.NET MVC?
¿qué pasa si borro los datos almacenados en caché? (6)
Necesito almacenar en caché algunos datos usando System.Web.Caching.Cache . No estoy seguro de si importa, pero los datos no provienen de una base de datos, sino de una gran cantidad de objetos personalizados.
El ASP.NET MVC es bastante nuevo para mí y me pregunto dónde tiene sentido que ocurra este almacenamiento en caché.
Modelo o controlador?
En cierto modo, esto tiene sentido para la caché en el nivel de Modelo , pero no necesariamente sé las implicaciones de hacer esto (en caso de haberlo). Si el almacenamiento en caché se hiciera a nivel del Controlador , ¿afectará eso a todas las solicitudes, o solo al HttpContext actual?
Entonces ... ¿dónde debería estar el almacenamiento en caché de datos de la aplicación, y cuál es una buena forma de hacerlo?
Actualizar
¡Gracias por las buenas respuestas! Todavía estoy tratando de reunir dónde tiene más sentido almacenar en caché dado los diferentes escenarios. Si uno almacena en caché toda la página, entonces tiene sentido mantenerla en la vista, pero ¿dónde dibujar la línea cuando no es toda la página?
Creo que el almacenamiento en caché debe estar relacionado de alguna manera con el modelo. Creo que el controlador no debería preocuparse más por los datos. La responsabilidad del controlador es asignar los datos, independientemente de dónde provengan, a las vistas.
Intenta también pensar por qué necesitas almacenar en caché? ¿Quieres guardar el procesamiento, la transmisión de datos o qué? Esto te ayudará a saber exactamente dónde necesitas tener tu capa de almacenamiento en caché.
No conozco la respuesta a su pregunta, pero Jeff Atwood habla sobre cómo el equipo de SO hizo el almacenamiento en caché utilizando el marco de MVC para .com en un reciente programa de minutos de hansel que podría ayudarlo:
Todo depende de qué tan costosa es la operación. Si tiene consultas complicadas, puede tener sentido almacenar en caché los datos en el nivel del controlador para que la consulta no se ejecute de nuevo (hasta que la caché caduque).
Tenga en cuenta que el almacenamiento en caché es un tema muy complicado. Hay muchos lugares diferentes donde puedes almacenar tu caché:
- Caché de Akamai / CDN
- Almacenamiento en caché del navegador
- Almacenamiento en memoria caché de aplicaciones en memoria
- Objeto Cache de .NET
- Directiva de la página
- Caché distribuida (memcached)
Yo elegiría el almacenamiento en caché en el nivel de modelo. (En general, el consejo parece ser minimizar la lógica de negocios en el nivel de controlador y mover tanto como sea posible en las clases de modelo).
¿Qué tal si lo haces así?
Tengo algunas entradas en el modelo representado por la clase Entry
y una fuente de entradas (desde una base de datos, o ''una plétora de objetos personalizados''). En el modelo, hago una interfaz para recuperar entradas:
public interface IEntryHandler { IEnumerable<Entry> GetEntries(); }
En el modelo tengo una implementación real de IEntryHandler
donde las entradas se leen desde el caché y se escriben en el caché.
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; } }
El controlador llamaría entonces a 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()); } }
De esta forma, es posible probar el controlador de forma unitaria sin tocar la memoria caché / base de datos / objetos personalizados.
Respuesta rápida
Comenzaría con el almacenamiento en memoria caché de CONTROLLER , usaría el atributo OutputCache y luego agregaría el caché de modelos si fuera necesario. Es más rápido de implementar y tiene resultados instantáneos.
Detalle Respuesta (porque me gusta el sonido de mi voz)
Aquí hay un ejemplo.
[OutputCache(Duration=60, VaryByParam="None")]
public ActionResult CacheDemo() {
return View();
}
Esto significa que si un usuario accede al sitio (para los requisitos de caché definidos en el atributo), hay menos trabajo por hacer. Si solo hay almacenamiento en caché de modelos, aunque la lógica (y probablemente el golpe de DB) esté en caché, el servidor web todavía tiene que renderizar la página. ¿Por qué hacer eso cuando el resultado del renderizado siempre será el mismo?
Así que comience con OutputCach
, luego vaya al almacenamiento en caché de Modelos mientras prueba su sitio.
El almacenamiento en caché de salida también es mucho más simple para empezar. No tiene que preocuparse por los problemas de almacenamiento en caché distribuidos en la granja de servidores web (si es parte de una granja de servidores) y el proveedor de almacenamiento en caché para el modelo.
Técnicas avanzadas de almacenamiento en caché
También puede aplicar el almacenamiento en caché de donut -> solo almacenar en caché parte de la página de UI :) ¡ Compruébelo !
Creo que en última instancia depende de lo que está almacenando en caché. Si desea almacenar en caché el resultado de las páginas representadas, está estrechamente relacionado con la naturaleza Http de la solicitud, y sugeriría un mecanismo de caché de nivel de ActionFilter.
Si, por otro lado, desea almacenar en caché los datos que dirigen las páginas, debe considerar el almacenamiento en caché a nivel de modelo. En este caso, al controlador no le importa cuando se generaron los datos, solo realiza las operaciones lógicas en los datos y los prepara para su visualización. Otro argumento para el almacenamiento en caché a nivel de modelo es si tiene otras dependencias en los datos del modelo que no están adjuntos a su contexto Http.
Por ejemplo, tengo una aplicación web donde la mayoría de mi Modelo se resume en un proyecto completamente diferente. Esto se debe a que habrá una segunda aplicación web que utilizará este mismo respaldo, Y existe la posibilidad de que tengamos una aplicación que no esté basada en la web y que también utilice los mismos datos. Gran parte de mis datos provienen de los servicios web, que pueden ser asesinos de rendimiento, por lo que tengo un caché de nivel modelo que los controladores y las vistas no saben absolutamente nada.