2010-06-15 11 views
3

Je développe une application C# Winform, c'est un client et se connecter au service Web pour obtenir des données. Les données renvoyées par webservice sont un DataTable. Le client l'affichera sur un DataGridView.Stocker les données de cache localement

Mon problème est le suivant: Le client mettra plus de temps à obtenir toutes les données du serveur (le service web n'est pas local avec le client). Je dois donc utiliser un fil pour obtenir des données. Voici mon modèle:

Le client crée un thread pour obtenir des données -> thread complet et envoyer un événement au client -> données d'affichage client sur datagridview sur un formulaire. Cependant, lorsque l'utilisateur ferme le formulaire, l'utilisateur peut ouvrir ce formulaire à un autre moment, et le client doit à nouveau récupérer les données. Cette solution provoquera le client lentement.

Donc, je pense à un cache de données:

client < --- get/ajouter/modifier/supprimer ---> --- obtenir les données du cache/ajouter/modifier/supprimer ---> Serveur (service web)

Veuillez me donner quelques suggestions. Exemple: les données mises en cache doivent être développées dans une autre application qui est la même hôte avec le client? Les données mises en cache sont en cours d'exécution dans le client. Veuillez me donner quelques techniques pour implémenter cette solution.

Si vous avez des exemples, s'il vous plaît donnez-moi.

Merci.

MISE À JOUR: Bonjour tout le monde, peut-être que vous pensez que mon problème jusqu'à présent. Je veux seulement mettre en cache des données dans la vie du client. Je pense que les données de cache doivent être stockées en mémoire. Et lorsque le client veut obtenir des données, il vérifie depuis le cache.

+0

Le cache ASP.NET n'a aucune dépendance à ASP.NET: http://aspalliance.com/1705_A_New_Approach_to_HttpRuntimeCache_Management.all –

+0

Mis à jour. J'ai seulement besoin que les données mises en cache soient disponibles dans la vie du client. Merci. –

Répondre

1

Vous pourriez essayer le Caching Application Block de Enterprise Library. Il est facile à utiliser, stocke en mémoire et, si jamais vous en avez besoin, il prend en charge l'ajout d'un emplacement de sauvegarde pour la durée de vie de l'application (base de données, stockage isolé, fichier, etc.) et même le cryptage .

Utilisez EntLib 3.1 si vous êtes bloqué avec .NET 2.0. Il n'y a pas beaucoup de nouveautés (pour la mise en cache, au moins) dans les EntLibs plus récents en plus d'un meilleur support de personnalisation.

0

Vous pouvez serialise le DataTable fichier: http://forums.asp.net/t/1441971.aspx

Votre seule préoccupation est alors de décider quand le cache est allé vicié. Peut-être horodater le fichier?

2

Avez-vous la possibilité d'apporter des modifications/ajouter au service Web?

Si vous pouvez Sync Services peut être une option pour vous. Vous pouvez définir quelles tables sont synchronisées et toutes les tâches de synchronisation sont gérées pour vous.

Découvrez

http://msdn.microsoft.com/en-us/sync/default.aspx

et crier si vous avez besoin de plus amples informations.

5

Si vous utilisez C# 2.0 et vous êtes prêt à expédier System.Web comme une dépendance, vous pouvez utiliser le cache ASP.NET:

using System.Web; 
using System.Web.Caching; 

Cache webCache; 

webCache = HttpContext.Current.Cache; 

// See if there's a cached item already 
cachedObject = webCache.Get("MyCacheItem"); 

if (cachedObject == null) 
{ 
    // If there's nothing in the cache, call the web service to get a new item 
    webServiceResult = new Object(); 

    // Cache the web service result for five minutes 
    webCache.Add("MyCacheItem", webServiceResult, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null); 
} 
else 
{ 
    // Item already in the cache - cast it to the right type 
    webServiceResult = (object)cachedObject; 
} 

Si vous n'êtes pas prêt Pour expédier System.Web, alors vous pouvez jeter un oeil à la Enterprise Library Caching block.

Si vous êtes sur .NET 4.0, cependant, la mise en cache a été poussée dans l'espace de noms System.Runtime.Caching. Pour l'utiliser, vous devez ajouter une référence à System.Runtime.Mise en cache, puis votre code ressemblera à quelque chose comme ceci:

using System.Runtime.Caching; 

MemoryCache cache; 
object cachedObject; 
object webServiceResult; 

cache = new MemoryCache("StackOverflow"); 

cachedObject = cache.Get("MyCacheItem"); 

if (cachedObject == null) 
{ 
    // Call the web service 
    webServiceResult = new Object(); 

    cache.Add("MyCacheItem", webServiceResult, DateTime.Now.AddMinutes(5)); 
} 
else 
{ 
    webServiceResult = (object)cachedObject; 
} 

Toutes ces mémoires cache sont en cours de traitement pour le client. Comme les données proviennent d'un service Web, comme Adam le dit, vous allez avoir de la difficulté à déterminer la fraîcheur des données. Vous devrez évaluer la fréquence à laquelle les données changent et la durée de mise en cache. les données pour.

0

Dans notre implémentation, chaque ligne de la base de données possède un horodatage mis à jour en dernier. Chaque fois que notre application cliente accède à une table, nous sélectionnons l'horodatage le plus récemment mis à jour depuis le cache et envoyons cette valeur au serveur. Le serveur répond avec toutes les lignes qui ont des horodatages plus récents.

1

Identifiez les objets que vous souhaitez sérialiser et mettez en cache le stockage isolé. Indiquez le niveau d'isolation des données que vous souhaitez (niveau d'application, niveau d'utilisateur, etc.).

Exemple:

Vous pouvez créer un sérialiseur générique, un échantillon très basique ressemblerait à ceci:

public class SampleDataSerializer 
{ 
    public static void Deserialize<T>(out T data, Stream stm) 
    { 
     var xs = new XmlSerializer(typeof(T)); 
     data = (T)xs.Deserialize(stm); 
    } 

    public static void Serialize<T>(T data, Stream stm) 
    { 
     try 
     { 
      var xs = new XmlSerializer(typeof(T)); 
      xs.Serialize(stm, data); 
     } 
     catch (Exception e) 
     { 
      throw; 
     } 
    } 
} 

Notez que vous devriez probablement mettre dans quelques surcharges au sérialisation et la désérialisation méthodes pour accueillir lecteurs, ou tout autre type que vous utilisez réellement dans votre application (par exemple, XmlDocuments, etc).

L'opération pour sauver à IsolatedStorage peut être géré par une classe utilitaire (exemple ci-dessous):

public class SampleIsolatedStorageManager : IDisposable 
{ 
    private string filename; 
    private string directoryname; 
    IsolatedStorageFile isf; 

    public SampleIsolatedStorageManager() 
    { 
     filename = string.Empty; 
     directoryname = string.Empty; 

     // create an ISF scoped to domain user... 
     isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | 
      IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain, 
      typeof(System.Security.Policy.Url), typeof(System.Security.Policy.Url)); 
    } 

    public void Save<T>(T parm) 
    { 
     using (IsolatedStorageFileStream stm = GetStreamByStoredType<T>(FileMode.Create)) 
     { 
      SampleDataSerializer.Serialize<T>(parm, stm); 
     } 
    } 

    public T Restore<T>() where T : new() 
    { 
     try 
     { 
      if (GetFileNameByType<T>().Length > 0) 
      { 
       T result = new T(); 

       using (IsolatedStorageFileStream stm = GetStreamByStoredType<T>(FileMode.Open)) 
       { 
        SampleDataSerializer.Deserialize<T>(out result, stm); 
       } 

       return result; 
      } 
      else 
      { 
       return default(T); 
      } 
     } 
     catch 
     { 
      try 
      { 
       Clear<T>(); 
      } 
      catch 
      { 
      } 

      return default(T); 
     } 
    } 

    public void Clear<T>() 
    { 
     if (isf.GetFileNames(GetFileNameByType<T>()).Length > 0) 
     { 
      isf.DeleteFile(GetFileNameByType<T>()); 
     } 
    } 

    private string GetFileNameByType<T>() 
    { 
     return typeof(T).Name + ".cache"; 
    } 

    private IsolatedStorageFileStream GetStreamByStoredType<T>(FileMode mode) 
    { 
     var stm = new IsolatedStorageFileStream(GetFileNameByType<T>(), mode, isf); 
     return stm; 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     isf.Close(); 
    } 
} 

Enfin, souvenez-vous d'ajouter les suivantes clauses utilisant:

using System.IO; 
using System.IO.IsolatedStorage; 
using System.Xml.Serialization; 

Le code réel à utiliser les classes ci-dessus pourrait ressembler à ceci:

var myClass = new MyClass(); 
myClass.name = "something"; 
using (var mgr = new SampleIsolatedStorageManager()) 
{ 
    mgr.Save<MyClass>(myClass); 
} 

Cela permettra d'économiser l'inst Vous spécifiez d'être enregistré dans le stockage isolé. Pour récupérer l'instance, appelez simplement:

using (var mgr = new SampleIsolatedStorageManager()) 
{ 
    mgr.Restore<MyClass>(); 
} 

Remarque: l'exemple fourni ne prend en charge qu'une instance sérialisée par type. Je ne suis pas sûr si vous avez besoin de plus que cela. Apportez les modifications nécessaires pour prendre en charge d'autres fonctionnalités.

HTH!

+0

Merci pour ça. Nouveau pour gagner des formes et c'est exactement l'approche que je cherchais. +1 IsolatedStorage – nullable

Questions connexes