15

所以我只是修复了我正在开发的框架中的一个错误。伪伪代码如下所示:

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 也更改了引用的缓存对象,所以它永远不会保存回数据库。我通过从缓存版本中克隆对象、切断引用并允许我将新对象与缓存对象进行比较来修复它。

我的问题是:有没有更好的方法来做到这一点,一些模式,你可以推荐?我不可能是唯一一个这样做过的人:)

4

3 回答 3

25

我认为,脏跟踪是处理这个问题的正常方法。就像是:

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();
于 2008-08-29T01:51:02.760 回答
1

我做过类似的事情,但我也通过克隆解决了这个问题。不同之处在于我让缓存进行了克隆。当你将一个对象放入缓存时,缓存会先克隆该对象并存储克隆的版本(这样你就可以在不污染缓存的情况下改变原始对象)。当您从缓存中获取对象时,缓存会返回对象的克隆而不是存储的对象(同样,调用者可以在不影响缓存/规范对象的情况下改变对象)。

我认为只要您存储/复制的数据很小,这是完全可以接受的。

于 2008-08-28T22:02:53.150 回答
1

使用 linq 时对 Marks anwser 的一点改进:

使用 Linq 时,从 DB 中获取实体会将每个对象标记为 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 可能会进一步改进。

于 2012-02-23T14:50:29.303 回答