2012-06-21 3 views
3

Je récupère une grande liste de nouvelles.Meilleure stratégie de mise en cache dans ce scénario particulier

Je veux utiliser la mise en cache de cette liste pour des raisons évidentes (exécuter une requête plus que nécessaire ne suffira pas).

Je lie cette liste à un répéteur sur lequel j'ai étendu pour activer la pagination (feuilleter entre les pages provoque le chargement de la page et donc une récupération de la liste à nouveau). La complication est le fait que ces nouvelles peuvent également être interrogées par date à partir d'une chaîne de requête 'année' qui est présente uniquement lors de l'interrogation des éléments de nouvelles par date.

est Ci-dessous le code pseudo pour ce que j'ai jusqu'à présent (coller le code réel ici prendrait trop de temps élaguant les tous les bits qui ajoutent simplement la confusion):

if(complete news items list are not cached OR querystring["year"] != null) 
{ 
    Int year = queryString["year"] (could be null) 
    Cache.Add(GetNewsItems(year)); 
} 
else 
{ 
    return cached newsItems; 
} 

Le problème est que lorsque le Le chargement de la page des éléments de nouvelles (à cause de la publication d'un contrôle de radiomessagerie) le paramètre [année] de la chaîne de requête sera toujours rempli et réitérera ainsi GetNewsItems. Aussi - même si l'URL de la maison (ie aucune chaîne de requête) est alors dirigée vers - en effet il y a toujours une version mise en cache des news pour ne pas chercher à les récupérer - mais ils PEUVENT être là pour une année donnée et ne sont donc pas pertinents pour un type de recherche «toutes les années». Est-ce que j'ajoute une nouvelle entrée de cache pour marquer quelle recherche a été effectuée le plus récemment? Quelles sont les considérations à prendre en compte lors de la mise en cache? Je peux ajouter une nouvelle chaîne de requête si besoin est (de préférence non) - cela résoudrait-il le problème?

Répondre

2

Pouvez-vous obtenir la liste complète sur la première requête, et cache ce (en supposant que ce n'est pas trop énorme)? Ensuite, pour toutes les requêtes suivantes, récupérez les données du cache et interrogez-les pour filtrer l'année que vous voulez.

Peut-être que vous pouvez stocker les données dans le cache sous forme de

IDictionary<int, IEnumerable<NewsItem>> 

(en supposant qu'il ya plus d'un NewsItem pour une année) où la clé est l'année de sorte que vous pouvez simplement récupérer un seul dictionnaire valeur paire pour obtenir les données d'une année.

Vous pouvez également mettre en cache les données par année, comme vous le faites dans votre exemple, et implémenter un mécanisme pour obtenir des données du cache pour chaque année si elle existe. Lorsque vous obtenez tout, vous pouvez soit obtenir tout le contenu du magasin de données et le mettre en cache séparément, soit implémenter un mécanisme pour déterminer les années qui manquent dans le cache et les obtenir. Personnellement, je pense que je voudrais aller à la mise en cache tout et le filtrage des données à partir du cache afin de ne pas encombrer la mémoire avec trop de données en cache.

Un modèle de TryGetValue utile pour obtenir du cache est quelque chose comme:

private bool TryGetValue<U>(string key, out U value) 
    { 
     object cachedValue = HttpContext.Current.Cache.Get(key); 
     if (cachedValue == null) 
     { 
      value = default(U); 
      return false; 
     } 
     else 
     { 
      try 
      { 
       value = (U)cachedValue; 
       return true; 
      } 
      catch 
      { 
       value = default(U); 
       return false; 
      } 
     } 
    } 
+0

Spot sur Robin. Merci beaucoup pour ça!! –

1

Je ne sais pas si cela peut être utile pour votre cas, mais vous pouvez ajouter le répéteur à un contrôle utilisateur et activer OutputCache pour elle, être invalidée par POST/GET params:

<%@ OutputCache Duration="100" VaryByParam="year" %> 
+0

+1, se penchera sur cela, mais je pense que je vais opter pour la solution de Robin pour l'instant. Merci beaucoup. –

Questions connexes