2009-06-24 17 views
29

Contesto: .Net 3.5, C#
Mi piacerebbe avere il meccanismo di memorizzazione nella cache nella mia applicazione Console.
Invece di reinventare la ruota, mi piacerebbe usare System.Web.Caching.Cache (e questa è una decisione definitiva, non posso usare altro framework di caching, non chiedere perché).
Tuttavia, sembra che System.Web.Caching.Cache debba essere eseguito solo in un contesto HTTP valido. Il mio molto semplice frammento di simile a questa:Come posso utilizzare System.Web.Caching.Cache in un'applicazione console?

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

Cache c = new Cache(); 

try 
{ 
    c.Insert("a", 123); 
} 
catch (Exception ex) 
{ 
    Console.WriteLine("cannot insert to cache, exception:"); 
    Console.WriteLine(ex); 
} 

e il risultato è:

 
cannot insert to cache, exception: 
System.NullReferenceException: Object reference not set to an instance of an object. 
    at System.Web.Caching.Cache.Insert(String key, Object value) 
    at MyClass.RunSnippet() 

Così, ovviamente, sto facendo qualcosa di sbagliato qui. Qualche idea?


Aggiornamento: +1 per la maggior parte delle risposte, ottenendo la cache tramite i metodi statici è l'uso corretto, vale a dire HttpRuntime.Cache e HttpContext.Current.Cache. Grazie a tutti!

risposta

56

La documentazione per il costruttore Cache indica che è solo per uso interno. Per ottenere l'oggetto Cache, chiama HttpRuntime.Cache piuttosto che creare un'istanza tramite il costruttore.

9

Basta usare lo Caching Application Block se non si desidera reinventare la ruota. Se si desidera ancora utilizzare la cache ASP.NET- see here. Sono abbastanza sicuro che funziona solo con .NET 2.0 e successivi. E 'semplicemente non era possibile utilizzare la cache al di fuori di ASP.NET in .NET 1.

MSDN ha una bella grande avviso nella pagina per la documentazione di cache troppo:

La classe Cache non è destinato all'uso al di fuori delle applicazioni ASP.NET. È stato progettato e testato per l'uso in ASP.NET per la memorizzazione nella cache delle applicazioni Web . In altri tipi di applicazioni , ad esempio le applicazioni della console o Windows Forms , la cache di ASP.NET potrebbe non funzionare correttamente .

Per una soluzione molto leggera, in cui non ci si deve preoccupare della scadenza ecc., Un oggetto dizionario può essere sufficiente.

+0

"vedi qui" collegamento è rotto –

+0

@ Ron- che è un bug StackOverflow. Ecco un TinyUrl per lo stesso collegamento: http://tinyurl.com/ms35eu – RichardOD

1

Prova

public class AspnetDataCache : IDataCache 
{ 
    private readonly Cache _cache; 

    public AspnetDataCache(Cache cache) 
    { 
     _cache = cache; 
    } 

    public AspnetDataCache() 
     : this(HttpRuntime.Cache) 
    { 

    } 
    public void Put(string key, object obj, TimeSpan expireNext) 
    { 
     if (key == null || obj == null) 
      return; 
     _cache.Insert(key, obj, null, DateTime.Now.Add(expireNext), TimeSpan.Zero); 
    } 

    public object Get(string key) 
    { 
     return _cache.Get(key); 
    } 

1

La classe System.Web.Caching.Cache si basa su avere il suo giocatore: "_cacheInternal" set dall'oggetto HttpRuntime.

Per utilizzare le classi System.Web.Caching, è necessario creare un oggetto HttpRuntime e impostare la proprietà HttpRuntime.Cache. Dovresti effettivamente emulare IIS.

è meglio usare altri framework di caching come:

+1

"L'unico modo per impostarlo è tramite metodi interni" - non vero, _cacheInternal viene impostato dalla proprietà statica accessor HttpRuntime.Cache. Tuttavia, sarei interessato a maggiori informazioni sul motivo per cui MSDN raccomanda che la cache di ASP.NET non sia utilizzata nelle app web non in-web. Ho un codice che lo usa (che risale prima dell'esistenza di questo avviso), e * sembra * funzionare correttamente. – Joe

+0

Grazie @Joe - modificato la mia risposta – d4nt

4

Ho finito in questa pagina chiedendo la stessa cosa. Ecco quello che sto facendo (che non mi piace ma sembra funzionare bene):

HttpContext context = HttpContext.Current; 
if (context == null) 
{ 
    HttpRequest request = new HttpRequest(string.Empty, "http://tempuri.org", string.Empty); 
    HttpResponse response = new HttpResponse(new StreamWriter(new MemoryStream())); 
    context = new HttpContext(request, response); 
    HttpContext.Current = context; 
} 
this.cache = context.Cache; 
+1

Questo è così sporco ma è stato davvero utile quando avevo un prototipo integrato con una dll esterna che si basava su HttpContext.Current.Cache e io avevo solo bisogno che funzionasse. Ho trovato una versione più breve qui: http://caioproiete.net/en/fake-mock-httpcontext-without-any-special-mocking-framework/ – bygrace

28

Mentre l'OP specificato v3.5, la questione è stato chiesto prima v4 è stato rilasciato. Per aiutare chi trova questa domanda e può vivere con una dipendenza v4, il team del framework ha creato una nuova cache per scopi generali per questo tipo di scenario. E 'nello spazio dei nomi System.Runtime.Caching: http://msdn.microsoft.com/en-us/library/dd997357%28v=VS.100%29.aspx

Il riferimento statica all'istanza di cache di default è: MemoryCache.Default

+0

Grazie per il suggerimento! –

+3

Molto utile! Sto cambiando le chiamate nella mia webapp per usare invece questo nuovo approccio. Ora questi metodi possono essere testati unitamente senza che sia necessario definire HttpContext.Cache. :) – ClearCloud8

Problemi correlati