Pergunta

Acabei de consertar um bug em um framework que estou desenvolvendo.O pseudo-pseudocódigo fica assim:

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

Então, essencialmente, eu estava obtendo um objeto do cache e, posteriormente, comparando o objeto original com o objeto armazenado em cache para ver se preciso salvá-lo no banco de dados, caso ele seja alterado.O problema surgiu porque o objeto original é uma referência... portanto, alterar someValue também alterou o objeto em cache referenciado, portanto, ele nunca seria salvo no banco de dados.Eu consertei clonando o objeto da versão em cache, cortando a referência e permitindo-me comparar o novo objeto com o armazenado em cache.

Minha pergunta é: existe uma maneira melhor de fazer isso, algum padrão que você possa recomendar? Não posso ser a única pessoa que já fez isso antes :)

Foi útil?

Solução

O rastreamento sujo é a maneira normal de lidar com isso, eu acho.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();

Outras dicas

Já fiz coisas semelhantes, mas também contornei isso clonando.A diferença é que mandei o cache fazer a clonagem.Quando você coloca um objeto no cache, o cache clonará o objeto primeiro e armazenará a versão clonada (para que você possa alterar o objeto original sem envenenar o cache).Quando você obtém um objeto do cache, o cache retorna um clone do objeto em vez do objeto armazenado (novamente para que o chamador possa alterar o objeto sem afetar o objeto armazenado em cache/canônico).

Acho que isso é perfeitamente aceitável, desde que os dados que você está armazenando/enganando sejam pequenos.

Uma pequena melhoria na resposta do Marks ao usar o linq:

Ao usar o Linq, a busca de entidades do banco de dados marcará cada objeto como IsDirty.Fiz uma solução alternativa para isso, não definindo IsDirty quando o valor não está definido;para esta instância:quando nulo.Para ints, coloquei o valor original em -1 e verifiquei isso.Isso não funcionará, entretanto, se o valor salvo for igual ao valor não inicializado (nulo no meu exemplo).

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

Provavelmente poderia ser melhorado configurando IsDirty após a inicialização de alguma forma.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top