Шаблоны кеширования в 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();

Итак, по сути, я получал объект из кэша, а затем сравнивал исходный объект с кэшированным объектом, чтобы узнать, нужно ли мне сохранить его в базе данных в случае его изменения. Проблема возникла потому, что исходный объект является ссылкой... поэтому изменение someValue также изменило ссылочный кэшированный объект, поэтому он никогда не сохранится обратно в базу данных. Я исправил это, клонировав объект из кэшированной версии, разорвав ссылку и позволив мне сравнить новый объект с кэшированным.

Мой вопрос: есть ли лучший способ сделать это, какой-то шаблон, который вы могли бы порекомендовать? Я не могу быть единственным человеком, который сделал это раньше:)

3 ответа

Решение

Думаю, грязный трекинг - нормальный способ справиться с этим. Что-то вроде:

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

Небольшое улучшение в Marks anwser при использовании linq:

При использовании Linq выборка объектов из БД помечает каждый объект как IsDirty. Я сделал обходной путь для этого, не устанавливая IsDirty, когда значение не установлено; для этого экземпляра: когда ноль. Для целочисленных значений я присвоил значение оригинала -1, а затем проверил его. Однако это не будет работать, если сохраненное значение совпадает с неинициализированным значением (в моем примере это значение равно null).

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

Вероятно, может быть улучшено путем установки IsDirty после инициализации.

Я делал подобные вещи, но клонировал и меня. Разница в том, что у меня кеш сделал кеш. Когда вы помещаете объект в кеш, кеш сначала клонирует объект и сохраняет клонированную версию (так что вы можете изменить исходный объект, не отравляя кеш). Когда вы получаете объект из кеша, кеш возвращает клон объекта вместо сохраненного объекта (опять же, чтобы вызывающая сторона могла видоизменить объект без воздействия на кешированный / канонический объект).

Я думаю, что это вполне приемлемо, если данные, которые вы храните / дублируете, невелики.

Другие вопросы по тегам