Pregunta

Quiero que un elemento de caché de ASP.NET se recicle cuando se toca un archivo específico, pero el siguiente código no funciona:

                       HttpContext.Current.Cache.Insert(
                            "Key",
                            SomeObject,
                            new CacheDependency(Server.MapPath("SomeFile.txt")),
                            DateTime.MaxValue,
                            TimeSpan.Zero,
                            CacheItemPriority.High,
                            null);

" SomeFile.txt " Parece que no se comprueba cuando llego a la memoria caché, y modificarlo no invalida este elemento.

¿Qué estoy haciendo mal?

¿Fue útil?

Solución

Problema resuelto:

Este fue un problema único e interesante, así que voy a documentar la causa y la solución aquí como una respuesta, para futuros buscadores.

Algo que omití en mi pregunta fue que esta inserción de caché estaba ocurriendo en una clase de servicio que implementaba el patrón de singleton.

En pocas palabras:

public class Service 
{
        private static readonly Service _Instance = new Service();
        static Service () { }
        private Service () { }

        public static Service Instance
        {
            get { return _Instance; }
        }

        // The expensive data that this service exposes      
        private someObject _data = null;

        public someObject Data
        {
            get
            {
                 if (_data == null)
                     loadData();
                 return _data;
            }
        }


        private void loadData()
        {
            _data = GetFromCache();
            if (_data == null)
            {
                 // Get the data from our datasource
                 _data = ExpensiveDataSourceGet();

                 // Insert into Cache
                 HttpContext.Current.Cache.Insert(etc);
            }
        }
}

Puede ser obvio para algunos, pero el culpable aquí es la carga perezosa dentro del patrón de singleton. Estaba tan atrapado pensando que el caché no estaba siendo invalidado, que olvidé que el estado del singleton se mantendría mientras el proceso de trabajo estuviera vivo.

Cache.Insert tiene una sobrecarga que le permite especificar un controlador de eventos para cuando se elimina el elemento de la memoria caché, mi primera prueba fue crear un controlador ficticio y establecer un punto de interrupción dentro de él. Una vez que vi que se estaba borrando el caché, me di cuenta de que " _data " no se restableció a nulo, por lo que la siguiente solicitud al singleton cargó el valor cargado perezoso.

En cierto sentido, tenía doble caché, aunque el caché de singleton fue muy breve, pero lo suficientemente largo como para ser molesto.

¿La solución?

 HttpContext.Current.Cache.Insert(
     "Key",
      SomeObject,
      new CacheDependency(Server.MapPath("SomeFile.txt")),
      DateTime.MaxValue,
      TimeSpan.Zero,
      CacheItemPriority.High,
      delegate(string key, object value, CacheItemRemovedReason reason)
      {
          _data = null;
      }
 );

Cuando se borra el caché, el estado dentro del singleton también debe borrarse ... problema resuelto.

Lección aprendida aquí? No ponga el estado en un singleton.

Otros consejos

¿Se está ejecutando ASP.NET bajo una cuenta con los permisos adecuados para el archivo especificado en la Dependencia de caché? Si no es así, entonces esta podría ser una de las razones por las que la Dependencia de caché no funciona correctamente.

Creo que deberás especificar una ruta:

var d = new CacheDependency(Server.MapPath("SomeFile.txt"));

Prepague con ~ \ App_Data según sea necesario.

Tu código me parece bien. Sin embargo, más allá de este fragmento, cualquier cosa podría estar sucediendo.

  • ¿Estás reinsertándote en cada devolución por casualidad?

  • Intente convertir su dependencia de caché en un campo de clase y verifíquelo en cada devolución. Modifique el archivo intermedio y vea si alguna vez se registra como " Modificado " ;. por ejemplo:

    public partial class _Default : System.Web.UI.Page
    {
       CacheDependency dep;
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            dep = new CacheDependency(Server.MapPath("SomeFile.txt"));
            HttpContext.Current.Cache.Insert(
                        "Key",
                        new Object(),
                        dep,
                        DateTime.MaxValue,
                            TimeSpan.Zero, CacheItemPriority.High, null);
        }
    
    
        if (dep.HasChanged)
            Response.Write("changed!");
        else
            Response.Write("no change :(");   }}
    

La única forma en que puedo reproducir este comportamiento es si la ruta proporcionada al constructor de CacheDependency no existe. La dependencia de caché no lanzará una excepción si la ruta no existe, por lo que puede ser un poco engañoso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top