2013-02-15 7 views
5

Ich habe dies in meinem Application_Start:ASP.NET MVC und MemoryCache - wie benutze ich es?

var cache = new MemoryCache("breadCrumbsNames"); 
var cacheItem = cache.GetCacheItem("nameOfCacheItem"); 

Aber dann CacheItem ist immer null, was mache ich falsch:

var crumbsCache = new MemoryCache("breadCrumbsNames"); 
var crumbsList = new List<CacheItem> 
        { 
         //list of new CacheItem(); 
        }; 
foreach (var cacheItem in crumbsList) 
{ 
    crumbsCache.Add(cacheItem, new CacheItemPolicy()); 
} 

Nun, ich dies in meinem Controller mache?

+0

prüfen diese http://www.deanhume.com/home/blogpost/object-caching----net -4/37 – Mate

Antwort

8

Sie erstellen eine neue Instanz von MemoryCache in jedem Controller. Da es neu ist, gibt es nichts darin, weshalb deine Werte immer null sind. Sie müssen auf dieselbe Instanz zugreifen, die Sie in Application_Start erstellt haben. Unter Verwendung von MemoryCache.Default untersuchen.

+0

Aber was genau ist "MemoryCache.Default"? Wenn ich zwei verschiedene Instanzen von Memcache einrichten würde, wie würde "MemoryCache.Default" wissen, welcher standardmäßig ist? – ojek

+0

Legen Sie MemoryCache fest.Standard entspricht der Instanz, die Sie verwenden möchten. –

10

Ich denke, eine bessere Option für Sie wäre, oder eine andere Abhängigkeit Injektion Framework zu verwenden, um Ihre MemoryCache in die Controller nach Bedarf zu injizieren.

Sie beginnen mit dem Hinzufügen von Ninject und Ninject.Mvc3 (und alle anderen verwandten Bits) zu Ihrem ASP.NET MVC-Projekt. Wenn Sie in Visual Studio arbeiten, können Sie dazu NuGet verwenden. Es ist ziemlich schmerzlos und gut automatisiert.

Der nächste Schritt wird sein, Ihre MemoryCache in eine Art einer Schnittstelle wickeln, wie zum Beispiel:

public interface IMemoryCacheService 
{ 
    MemoryCache MemoryCache 
    { 
     get; 
     set; 
    } 
} 

Und:

public class MemoryCacheService : IMemoryCacheService 
{ 
    public MemoryCacheService() 
    { 
     MemoryCache = new MemoryCache(); 
    } 

    public MemoryCache MemoryCache 
    { 
     get; 
     set; 
    } 
} 

Dann wird eine Bindung innerhalb Ninject Sie definieren, so dass Ninject weiß Wenn Sie etwas vom Typ IMemoryCacheService benötigen, sollte es Ihnen die Instanz MemoryCacheService geben.

Ich werde meine eigene Ninject Config-Klasse hier einfügen. Die Datei, die in Ihrem Projekt erstellt wird, ist sehr ähnlich und befindet sich in einem Ordner namens App_Start (der automatisch erstellt wird, wenn Sie NuGet verwenden). Die Klasse, die Ninject standardmäßig erstellt, heißt NinjectWebCommon.

public class HomeController : Controller 
{ 
    public ActionResult Foo() 
    { 
     ... 
    } 

    ... 
} 

zu:

public class HomeController : Controller 
{ 
    private IMemoryCacheService memoryCacheService; 

    public HomeController(IMemoryCacheService memoryCacheService) 
    { 
     this.memoryCacheService = memoryCacheService; 
    } 

    public ActionResult Foo() 
    { 
     // use this.memoryCacheService in your controller methods... 
    } 

    ... 
} 

Sag mal, du auch einen anderen Dienst gemacht IEmailService nach der oben genannten Strategie genannt, und Sie

public static class NinjectConfig 
{ 
    private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 

    public static void Start() 
    { 
     DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); 
     DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); 

     bootstrapper.Initialize(CreateKernel); 
    } 

    public static void Stop() 
    { 
     bootstrapper.ShutDown(); 
    } 

    private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 

     kernel.Bind<Func<IKernel>>() 
       .ToMethod(context =>() => new Bootstrapper().Kernel); 
     kernel.Bind<IHttpModule>() 
       .To<HttpApplicationInitializationHttpModule>(); 
     kernel.RegisterServices(); 

     return kernel; 
    } 

    private static void RegisterServices(this IKernel kernel) 
    { 
     kernel.Bind<IMemoryCacheService>() 
       .To<MemoryCacheService>() 
       .InSingletonScope(); 
       // InSingletonScope() is important so Ninject knows 
       // to create only one copy and then reuse it every time 
       // it is asked for 

     // ignore the stuff below... I have left it in here for illustration 
     kernel.Bind<IDbTransactionFactory>() 
       .To<DbTransactionFactory>() 
       .InRequestScope(); 
     kernel.Bind<IDbModelContext>() 
       .To<DbModelContext>() 
       .InRequestScope(); 
     kernel.Bind<IDbModelChangeContext>() 
       .To<DbModelChangeContext>() 
       .InRequestScope(); 
     kernel.Bind<IUserContext>() 
       .To<UserContext>() 
       .InRequestScope(); 

     kernel.BindAttributeAndFilter<IgnoreNonAjaxRequestsFilter, IgnoreNonAjaxRequestsAttribute>(); 
     kernel.BindAttributeAndFilter<ProvideApplicationInfoFilter, ProvideApplicationInfoAttribute>(); 
     kernel.BindAttributeAndFilter<ProvideSessionInfoFilter, ProvideSessionInfoAttribute>(); 
     kernel.BindAttributeAndFilter<UseDialogLayoutFilter, UseDialogLayoutAttribute>(); 
     kernel.BindAttributeAndFilter<CheckResourceAccessFilter, CheckResourceAccessAttribute>(); 
     kernel.BindAttributeAndFilter<CheckResourceStateFilter, CheckResourceStateAttribute>(); 
    } 

    private static void BindAttributeAndFilter<TFilter, TAttribute>(this IKernel kernel) 
    { 
     kernel.BindFilter<TFilter>(FilterScope.Action, null) 
       .WhenControllerHas<TAttribute>(); 
     kernel.BindFilter<TFilter>(FilterScope.Action, null) 
       .WhenActionMethodHas<TAttribute>(); 
    } 
} 

Schließlich wird Ihre Controller aus ändern wollte IEmailService auch in HomeController verfügbar sein, dann:

public class HomeController : Controller 
{ 
    private IMemoryCacheService memoryCacheService; 
    private IEmailService emailService; 

    public HomeController(IMemoryCacheService memoryCacheService, IEmailService emailService) 
    { 
     this.memoryCacheService = memoryCacheService; 
     this.emailService = emailService; 
    } 

    public ActionResult Foo() 
    { 
     // use this.memoryCacheService in your controller methods... 
     // and also use this.emailService in your controller methods... 
    } 

    ... 
} 

Ninject wird die ASP.NET MVC-Controller-Factory ändern, um automatisch die injizierten Argumente den Controller-Konstruktoren bereitzustellen.

Ich denke, diese Art von Ansatz auf lange Sicht besser ist, die globale Variablen zu halten usw.

+3

Ich bin der Meinung, dass dies mehr Overhead als Wert für die meisten Situationen hinzufügt. [Bearbeitet, um hinzuzufügen: dies kann für verteilte Caches geeignet sein.] Verwenden Sie einfach MemoryCache.Default wie von Ryan Byrne beschrieben. –

+0

Ich schrieb alle oben genannten mehr, um den richtigen Ansatz zu veranschaulichen, als die spezifische Frage zu beantworten, wenn ich ehrlich bin. Das Kernproblem bestand darin, dass das OP versuchte, ein Objekt in einem Controller zu erstellen (was pro Anforderung sein würde), während er ein Singleton benötigte. Im Allgemeinen möchten wir Abhängigkeiten injizieren, anstatt statische Klassen/Eigenschaften zu verwenden. –

+1

Wenn Sie den Kommentar des OP zu Ryan Byrnes Antwort lesen, ist es ganz klar, dass das OP (wahrscheinlich ohne Wissen des OP) nach einem DI-Mechanismus sucht und nicht nur nach einer ordnungsgemäß initialisierten globalen Variablen. –

Verwandte Themen