Pregunta

Así que acabo de arreglar un error en un marco que estoy desarrollando.El pseudopseudocódigo tiene este aspecto:

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();

Entonces, esencialmente, estaba obteniendo un objeto del caché y luego comparando el objeto original con el objeto almacenado en caché para ver si necesito 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 cambiar algún valor también cambió el objeto almacenado en caché al que se hace referencia, por lo que nunca se volvería a guardar en la base de datos.Lo solucioné 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: ¿Existe una mejor manera de hacer esto, algún patrón, que puedas recomendar? No puedo ser la única persona que ha hecho esto antes :)

¿Fue útil?

Solución

Creo que el seguimiento sucio es la forma normal de manejar esto.Algo 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();

Otros consejos

He hecho cosas similares, pero también lo solucioné clonando.La diferencia es que hice que el caché hiciera la clonación.Cuando coloca un objeto en el caché, el caché clonará el objeto primero 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 la persona que llama pueda mutar el objeto sin afectar el objeto almacenado en caché/canónico).

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

Una pequeña mejora en la respuesta de Marks cuando se usa linq:

Al usar Linq, recuperar entidades de la base de datos marcará cada objeto como IsDirty.Hice una solución para esto al no configurar IsDirty cuando el valor no está establecido;para este caso:cuando es nulo.Para ints, puse el valor original en -1 y luego lo verifiqué.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 configurando IsDirty después de la inicialización de alguna manera.

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