2008-08-28 31 views
11

Así que acabo de arreglar un error en un marco que estoy desarrollando. El pseudo-pseudocódigo es el siguiente:Patrones de almacenamiento en caché en ASP.NET

myoldObject = new MyObject { someValue = "old value" }; 
cache.Insert("myObjectKey", myoldObject); 
myNewObject = cache.Get("myObjectKey"); 
myNewObject.someValue = "new value"; 
if(myObject.someValue != cache.Get("myObjectKey").someValue) 
    myObject.SaveToDatabase(); 

Así que, esencialmente, que estaba recibiendo un objeto de la caché, y luego más tarde en la comparación del objeto original al objeto almacenado en caché para ver si tengo que guardarlo en la base de datos en caso de que haya cambiado. El problema surgió porque el objeto original es una referencia ... por lo que el cambio de algún valor también cambió el objeto en caché al que se hace referencia, por lo que nunca se guardará de nuevo en la base de datos. Lo arreglé clonando el objeto de la versión almacenada en caché, cortando la referencia y permitiéndome comparar el nuevo objeto con el almacenado en caché.

Mi pregunta es: ¿hay alguna manera mejor de hacer esto, algún patrón que usted pueda recomendar? No puedo ser la única persona que ha hecho esto antes :)

Respuesta

20

El rastreo sucio es la forma normal de manejar esto, creo. Algo así como:

class MyObject { 
    public string SomeValue { 
    get { return _someValue; } 
    set { 
     if (value != SomeValue) { 
      IsDirty = true; 
      _someValue = value; 
     } 
    } 

    public bool IsDirty { 
    get; 
    private set; 
    } 

    void SaveToDatabase() { 
    base.SaveToDatabase(); 
    IsDirty = false; 
    } 
} 

myoldObject = new MyObject { someValue = "old value" }; 
cache.Insert("myObjectKey", myoldObject); 
myNewObject = cache.Get("myObjectKey"); 
myNewObject.someValue = "new value"; 
if(myNewObject.IsDirty) 
    myNewObject.SaveToDatabase(); 
+0

Hay muchas cosas que no sé sobre lenguajes y sintaxis. +1 porque aprendí que puedes hacer que un setter sea privado dentro de una propiedad pública. Awesomeness sobreviene! – theo

+0

@theo: solo en versiones posteriores de .NET (creo 2.0+, tal vez 3.0?) – Broam

1

He hecho cosas similares, pero logré clonarlo también. La diferencia es que tuve el caché de hacer la clonación. Cuando coloca un objeto en el caché, el caché clonará primero el objeto y almacenará la versión clonada (para que pueda mutar el objeto original sin envenenar el caché). Cuando obtiene un objeto del caché, el caché devuelve un clon del objeto en lugar del objeto almacenado (nuevamente para que el que llama pueda mutar el objeto sin afectar el objeto caché/canónico).

Creo que esto es perfectamente aceptable siempre que los datos que está almacenando/engañando sean pequeños.

1

Una pequeña mejora en las marcas anwser al utilizar LINQ:

Al utilizar LINQ, ir a buscar las entidades de base de datos va a marcar cada objeto como IsDirty. Hice una solución para esto, al no configurar IsDirty cuando el valor no está establecido; para esta instancia: cuando es nulo. Para los ints, senté el valor original en -1, y luego lo revisé. Sin embargo, esto no funcionará si el valor guardado es el mismo que el valor no inicializado (nulo en mi ejemplo).

private string _name; 
[Column] 
public string Name 
{ 
    get { return _name; } 
    set 
    { 
     if (value != _name) 
     { 
      if (_name != null) 
      { 
       IsDirty = true; 
      } 
      _name = value; 
     } 
    } 
} 

probablemente podría mejorarse aún más mediante el establecimiento de IsDirty después de la inicialización de alguna manera.

Cuestiones relacionadas