2008-08-28 6 views
11

J'ai donc corrigé un bogue dans un framework que je suis en train de développer. Le pseudo-pseudo ressemble à ceci:Modèles de cache dans 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(); 

Donc, essentiellement, je recevais un objet à partir du cache, puis plus tard en comparant l'objet original à l'objet mis en cache pour voir si je dois sauver la base de données au cas où il est changé. Le problème est survenu parce que l'objet d'origine est une référence ... donc changer someValue a également changé l'objet mis en cache référencé, donc il ne sauvegardera jamais dans la base de données. Je l'ai corrigé en clonant l'objet hors de la version en cache, en coupant la référence et en me permettant de comparer le nouvel objet avec celui en cache.

Ma question est: Y at-il une meilleure façon de le faire, un modèle, que vous pourriez recommander? Je ne peux pas être la seule personne à avoir fait ça auparavant :)

Répondre

20

Le suivi sale est la façon normale de gérer cela, je pense. Quelque chose comme:

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

Il y a beaucoup de choses que je ne connais pas sur les langues et la syntaxe. +1 parce que j'ai appris que vous pouvez rendre un setter privé dans une propriété publique. Awesomeness s'ensuit! – theo

+0

@theo: Seulement dans les versions ultérieures de .NET (je crois 2.0+, peut-être 3.0?) – Broam

1

J'ai fait des choses similaires, mais je l'ai fait aussi par clonage. La différence est que j'ai eu le cache faire le clonage. Lorsque vous placez un objet dans le cache, le cache clone d'abord l'objet et stocke la version clonée (de sorte que vous pouvez muter l'objet d'origine sans empoisonner le cache). Lorsque vous obtenez un objet du cache, le cache renvoie un clone de l'objet au lieu de l'objet stocké (à nouveau pour que l'appelant puisse muter l'objet sans affecter l'objet mis en cache/canonique). Je pense que cela est parfaitement acceptable tant que les données que vous stockez/duper sont petites.

1

Un peu d'amélioration sur les marques anwser lors de l'utilisation LINQ:

Lorsque vous utilisez LINQ, aller chercher des entités de DB marquera tous les objets comme IsDirty. J'ai fait une solution de contournement pour cela, en ne définissant pas IsDirty lorsque la valeur n'est pas définie; pour cette instance: quand null. Pour ints, j'ai placé la valeur orig à -1, puis vérifié pour cela. Cela ne fonctionnera pas, cependant, si la valeur enregistrée est la même que la valeur non initialisée (null dans mon exemple).

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

Pourrait probablement être amélioré en définissant IsDirty après l'initialisation d'une manière ou d'une autre.

Questions connexes