質問
そこで、開発中のフレームワークのバグを修正しました。擬似擬似コードは次のようになります。
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 を変更すると、参照されたキャッシュされたオブジェクトも変更されるため、データベースに保存されなくなります。キャッシュされたバージョンからオブジェクトのクローンを作成し、参照を切断して、新しいオブジェクトをキャッシュされたオブジェクトと比較できるようにすることで、この問題を修正しました。
私の質問は次のとおりです。 これを行うためのより良い方法、または推奨できるパターンはありますか? 以前にこれをやったのは私だけではないはずです:)
解決
ダーティ・トラッキングがこれに対処する通常の方法だと思います。何かのようなもの:
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();
他のヒント
私も同様のことをしましたが、クローンを作成することで回避しました。違いは、キャッシュを使用してクローンを作成したことです。オブジェクトをキャッシュに入れると、キャッシュは最初にオブジェクトのクローンを作成し、クローンされたバージョンを保存します (そのため、キャッシュを汚染することなく元のオブジェクトを変更できます)。キャッシュからオブジェクトを取得すると、キャッシュは保存されているオブジェクトではなくオブジェクトのクローンを返します (これにより、呼び出し元はキャッシュ/正規オブジェクトに影響を与えることなくオブジェクトを変更できます)。
保存/複製しているデータが小さい限り、これは完全に許容できると思います。
linq を使用する場合の Marks anwser を少し改善しました。
Linq を使用する場合、DB からエンティティを取得すると、すべてのオブジェクトが IsDirty としてマークされます。この問題を回避するには、値が設定されていない場合は IsDirty を設定しないようにしました。この例の場合:nullの場合。int の場合は、orig-value を -1 に設定してから、それをチェックしました。ただし、保存された値が初期化されていない値 (この例では null) と同じ場合、これは機能しません。
private string _name;
[Column]
public string Name
{
get { return _name; }
set
{
if (value != _name)
{
if (_name != null)
{
IsDirty = true;
}
_name = value;
}
}
}
おそらく初期化後に IsDirty を設定することでさらに改善される可能性があります。