views:

624

answers:

3

So I just fixed a bug in a framework I'm developing. The pseudo-pseudocode looks like this:

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

So, essentially, I was getting an object from the cache, and then later on comparing the original object to the cached object to see if I need to save it to the database in case it's changed. The problem arose because the original object is a reference...so changing someValue also changed the referenced cached object, so it'd never save back to the database. I fixed it by cloning the object off of the cached version, severing the reference and allowing me to compare the new object against the cached one.

My question is: is there a better way to do this, some pattern, that you could recommend? I can't be the only person that's done this before :)

+1  A: 

I've done similar things, but I got around it by cloning too. The difference is that I had the cache do the cloning. When you put an object into the cache, the cache will clone the object first and store the cloned version (so you can mutate the original object without poisoning the cache). When you get an object from the cache, the cache returns a clone of the object instead of the stored object (again so that the caller can mutate the object without effecting the cached/canonical object).

I think that this is perfectly acceptable as long as the data you're storing/duping is small.

Craig Walker
+8  A: 

Dirty tracking is the normal way to handle this, I think. Something like:

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();
Mark Brackett
There's lots of things that I don't know about languages and syntax. +1 because I learned that you can make a setter private inside a public property. Awesomeness ensues!
theo
@theo: Only in later versions of .NET (I believe 2.0+, maybe 3.0?)
Broam
A: 

I agree with the dirty caching technique. You may try CSLA.NET business object framework for that scenario.