2008-08-28 5 views
11

Also habe ich gerade einen Fehler in einem Framework behoben, das ich entwickle. Der Pseudo-Pseudo-Code sieht wie folgt aus:Caching-Muster in 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(); 

, also im Wesentlichen, ich war immer ein Objekt aus dem Cache, und dann später auf das ursprüngliche Objekt auf das zwischengespeicherte Objekt zu vergleichen, um zu sehen, ob ich es die sparen muß Datenbank für den Fall, dass es geändert wird. Das Problem trat auf, weil das ursprüngliche Objekt eine Referenz war ... also änderte someValue auch das referenzierte zwischengespeicherte Objekt, so dass es niemals in die Datenbank zurückspeichern würde. Ich habe es behoben, indem ich das Objekt von der zwischengespeicherten Version geklont habe, die Referenz durchtrennt und mir erlaubt habe, das neue Objekt mit dem zwischengespeicherten zu vergleichen.

Meine Frage ist: gibt es eine bessere Möglichkeit, dies zu tun, einige Muster, die Sie empfehlen könnten? Ich kann nicht die einzige Person sein, die das schon einmal gemacht hat :)

Antwort

20

Schmutzige Tracking ist der normale Weg, um damit umzugehen, denke ich. Etwas wie:

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

Es gibt viele Dinge, die ich nicht über Sprachen und Syntax weiß. +1, weil ich gelernt habe, dass Sie einen Setter in einer öffentlichen Eigenschaft privat machen können. Awesomeness folgt! – theo

+0

@theo: Nur in späteren Versionen von .NET (ich glaube 2.0+, vielleicht 3.0?) – Broam

1

Ich habe ähnliche Sachen gemacht, aber ich habe es auch durch Klonen geschafft. Der Unterschied ist, dass ich den Cache das Klonen machen ließ. Wenn Sie ein Objekt in den Cache stellen, klont das Cache zuerst das Objekt und speichert die geklonte Version (so können Sie das ursprüngliche Objekt mutieren, ohne den Cache zu vergiften). Wenn Sie ein Objekt aus dem Cache abrufen, gibt der Cache anstelle des gespeicherten Objekts einen Klon des Objekts zurück (wiederum, damit der Aufrufer das Objekt mutieren kann, ohne das zwischengespeicherte/kanonische Objekt zu beeinflussen).

Ich denke, dass dies vollkommen akzeptabel ist, solange die Daten, die Sie speichern/duping ist klein.

1

Eine kleine Verbesserung auf Marks anwser wenn Linq mit:

Wenn Linq verwenden, Einheiten von DB holen wird jedes Objekt als IsDirty markieren. Ich habe einen Workaround dafür gemacht, indem ich IsDirty nicht gesetzt habe, wenn der Wert nicht gesetzt ist; für diese Instanz: wenn null. Für Ints setzte ich den orig-Wert auf -1 und prüfte das dann. Dies funktioniert jedoch nicht, wenn der gespeicherte Wert dem nicht initialisierten Wert entspricht (in meinem Beispiel null).

Konnte wahrscheinlich weiter verbessert werden, indem man IsDirty nach der Initialisierung irgendwie einstellt.