2010-06-21 7 views
9

Quiero almacenar una pequeña lista de un objeto simple (que contiene tres cadenas) en mi aplicación ASP.NET MVC. La lista se carga desde la base de datos y rara vez se actualiza editando algunos valores en el área de administración del sitio.Uso de HttpContext.Current.Application para almacenar datos simples

Estoy pensando en usar HttpContext.Current.Application para almacenarlo. De esta manera puedo cargarlo en el Global.asax:

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 

     HttpContext.Current.Application["myObject"] = loadDataFromSql(); // returns my object 
    } 

Y a continuación, puede hacer referencia fácilmente desde cualquier controlador o vistas según sea necesario. Entonces, en caso de que el área de administración llame a la acción del controlador updateMyObject, puedo simplemente actualizar el DB y cargarlo nuevamente y reemplazar HttpContext.Current.Application["myObject"].

¿Hay alguna desventaja para hacer esto? Parece que va a funcionar bien para lo que estoy tratando de lograr, sin embargo, ¿alguien sabe de una mejor manera de hacerlo, suponiendo que hay una gran desventaja en el método que he presentado?

+1

¿Qué sucede cuando se actualiza la lista? ¿Vas a restablecer la aplicación cada vez? –

Respuesta

27

Lo que realmente hace es Caché, y es genial, ya que reduce las llamadas a un almacenamiento externo (una base de datos o un archivo, lo que sea). La compensación es el uso de la memoria, por supuesto. Ahora, casi cualquier marco web moderno, incluido ASP.NET, incluye algún tipo de mecanismo de almacenamiento en caché. O lo usa, o usa algún tipo de variable global.

Almacenar datos en el objeto Cache incorporado de ASP.NET tiene algunas ventajas significativas, ya que este mecanismo realmente verifica el uso de la memoria y elimina los datos en caché de acuerdo con algunas reglas.

Sin embargo, si los datos que desea almacenar en caché se utilizan intensamente en toda la aplicación, y su tamaño no es demasiado grande (digamos, más pequeño que 1 MB), es posible que desee almacenarlo como una variable global.

En ASP.NET, las variables globales se logran utilizando el objeto Application, como describió en su pregunta, o escribiendo propiedades/campos públicos estáticos en una clase interna/pública.

Aquí está mi solución a las propiedades estáticas. Tenga en cuenta que utilizo un objeto de bloqueo para proteger los datos internos de la corrupción. Se ve así:

public class WhateverClass 
{ 
    private static object theLocker = new object(); 
    private static YourDataType theData; 
    public static YourDataType TheData 
    { 
    get 
    { 
     lock (theLocker) 
     { 
     return theData; 
     } 
    } 
    set 
    { 
     lock (theLocker) 
     { 
     theData = value; 
     } 
    } 
    } 
} 

El uso es muy sencillo:

primera vez, en Application_Start:

protected void Application_Start() 
{ 
    RegisterRoutes(RouteTable.Routes); 

    WhateverClass.TheData = loadDataFromSql(); 
} 

En cualquier controlador:

var myData = WhateverClass.TheData; 

Este enfoque es mejor porque tiene seguridad de tipo, ya que esta propiedad pública estática se puede declarar explícitamente con el tipo exacto. Además, este tipo de almacenamiento es más comprobable ya que no depende del contexto web.

HTH!

+0

Gracias, esto es lo que estaba buscando. – macca1

+0

¡Realmente gracias !, es útil para mí. Pero en mi caso (ASP.NET API), tengo que almacenar datos más grandes en la memoria (1GB a partir de ahora (y contar), que es más de 10.000 registros - para ser almacenados en la lista/diccionario. ¿Debo ir con su enfoque – hungdoan

+1

@hungdoan, usaría una solución como MemCache, un servicio de caché externo. No creo que almacenar más de 1 GB para el almacenamiento en caché de la aplicación ASP.NET sea una buena idea. –

0

Application_Start realmente solo se activa en App Pool Recylce, IIS resuelve o reinicia. Si actualiza estos valores con poca frecuencia, ¿por qué no los almacena en su web.config y accede a ellos de esa manera?

Dicho esto, no creo que haya nada malo con su enfoque. Aunque más típicamente he visto personas que usan archivos de configuración para valores que raramente cambian.

3

Si se está implementando en un solo servidor web, el enfoque funcionaría. Considere el objeto Caché para esto, ya que proporciona más opciones para la caducidad si necesita dicha funcionalidad. (Consulte una comparación, aunque sea antigua, here.)

Si alguna vez va a implementar en una granja de servidores web o su equivalente, debe usar memcached u otro mecanismo de almacenamiento en caché compatible con la granja web. Los objetos Application y Cache solo existen normalmente en un contexto de servidor único; si su usuario podría estar accediendo a varios servidores web durante su sesión (y el caché debe ser idéntico) necesitará un caché compartido que se pueda ver desde cada uno de los posibles servidores web.

Independientemente de la ruta que tome, deberá invalidar/volver a cargar su caché siempre que los datos subyacentes cambien, que es un código personalizado que varía según la aplicación.

Este enfoque funciona bien y puede acelerar las cosas considerablemente, pero es un poco más trabajo que usted puede darse cuenta a primera vista ...

+0

Gracias por la respuesta perspicaz. Solo estoy implementando en un solo servidor, pero esto es interesante de observar en una granja de servidores web. – macca1

6

HttpContext.Current.Application es esencialmente una resaca que se necesita para la compatibilidad hacia atrás con ASP clásico. Básicamente es una Hashtable estática con semántica de bloqueo de ASP clásica (Application.Lock/Application.UnLock).

Como Hashtable de tipo débil, tendrá que emitir objetos a recuperar:

MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"]; 

En una aplicación ASP.NET que no es una migración de ASP clásico, yo preferiría usar otra norma .NET cosas, como por ejemplo:

  • un campo estático, utilizando .NET semántica de bloqueo si se necesitan bloqueos (por ejemplo, la palabra clave de bloqueo de C#, o una instancia ReaderWriterLockSlim, dependiendo de sus necesidades):

    estático MyObject myObject = LoadFromSql();

  • El Cache de ASP.NET - que tiene numerosas funciones para la gestión de caducidad, dependencias, ...

2

Sí, utilizando HttpContext.Current.Application va a funcionar muy bien para lo que está haciendo. No hay problemas.

"HttpContext.Current.Application" es simplemente una referencia al objeto estático global "HttpApplicationState" en .NET para su aplicación web, del que debe haber una instancia global por aplicación web. Al almacenar datos allí, proporciona acceso rápido y seguro para subprocesos a sus variables globales. Asegúrese de encerrarlos en la actualización de los valores, como en este ejemplo:

System.Web.HttpContext.Current.Application.Lock(); 
System.Web.HttpContext.Current.Application["WebApplicationPath"] = MyWebApplicationPath; 
System.Web.HttpContext.Current.Application.UnLock(); 

Como otros han mencionado, también puede crear una serie de clases estáticas en su App_Code o en otra carpeta y no almacenar los valores estáticos globales, así como sus valores de HttpContext.Current.Application, donde se pueden verificar de forma segura los valores o actualizarse desde la base de datos, o actualizarse y verificarse entre sí, trabajando en tándem. Normalmente creo una clase global estática para ayudar en la administración y recuperación de las variables de aplicación que almaceno. De esta forma, tiene el diccionario de estado de la clase HttpApplicationState y los objetos estáticos de la aplicación web trabajando en conjunto para compartir y mantener valores globales.(Tenga en cuenta que cada clase estática se asigna por proceso de trabajo y puede haber hasta 10 WP en promedio de forma predeterminada en muchos servidores web/aplicaciones web. Por lo tanto, mantenga los datos en tipos estáticos al mínimo.)

Mantener en mente ya que algunas granjas de servidores mencionadas no comparten el estado de la Aplicación. Hay muchas formas de manejar esto. No soy partidario de la memoria caché debido a las formas en que puede caducar, fallar, quedarse obsoleta o dañarse. Una solución más simple es usar simplemente la base de datos y las cadenas de consulta url para comunicarse entre servidores y mantener el estado. ¡Buena suerte!

+0

¿Existe una restricción de tamaño máximo para los datos que ingresa en una entrada para 'System.Web.HttpContext.Current.Application'. Por ejemplo, una entrada con 50MB? – Heinrich

Cuestiones relacionadas