2010-08-25 17 views
8

Ich habe eine kleine ASP.NET MVC 2-Site zusammengestellt, die einige sehr umfangreiche date mining/table-joins/etc.SQL Caching und Entity Framework

Mit MVC habe ich einen Controller, der die Daten in vielen verschiedenen Formen (Tabellen, Bilder usw.) zurückgibt. So speichern Sie die Datenbank schlagen häufig habe ich einen Dual-Cache-Mechanismus:

  1. Für identische Parameter auf die gleiche Aktion ich die OutputCacheAttribute mit VaryByParam = "*" verwenden.
  2. Angenommen, einige Parameter der Aktion haben sich geändert (oder eine andere Aktion wird aufgerufen), ist es möglich, dass meine "Daten" zuvor angefordert wurden, also speichere ich die Daten in einem Ansichtsmodell nach dem ersten Treffer der Datenbank, Ich erreiche dies mit einem .NET 4.0 System.Runtime.Caching.ObjectCache.

Beispiel der ObjectCache innerhalb des Controllers:

private static readonly ObjectCache cache = 
     new MemoryCache("CompareControllerCache"); 
private static void CacheObject(ViewModel obj, 
           string param1, 
           int someOtherParam) 
{ 
    string key = string.Format("{0}-{1}", param1, someOtherParam); 
    Trace.WriteLine(string.Format("Adding {0} to the cache", key)); 
    cache.Add(key, obj, new CacheItemPolicy 
     { 
      SlidingExpiration = TimeSpan.FromMinutes(1) 
     }); 
} 

// Corresponding GetCachedObject with similar key defining logic. 

Das gibt ihm eine gute Performance-Verbesserung, aber wo es nicht auf den CacheItemPolicy sehr einfach ist. Im Idealfall möchte ich, dass das Cache-Fenster größer ist, aber das zwischengespeicherte Element abläuft, wenn sich die Datenbank ändert.

Die CacheItemPolicy scheint dies mit der ChangeMonitors Sammlung zu unterstützen, auf die ich ein SqlChangeMonitor hinzufügen könnte, aber wenn dies zu konstruieren versucht, wo ich zum Stillstand kommen.

Ich benutze Entity Framework 4 für den Zugriff auf eine SQL-Datenbank, wie Wie baue ich die SqlChangeMonitor, um die paar Datenbanktabellen zu überwachen, die wahrscheinlich einen Cache-Ablauf auslösen?

SqlChangeMonitor ist mit einem SqlDependency konstruiert, die SqlCommand ein nimmt - wie kann ich auf Entity Framework Verkapselung von meiner Datenbank einklinken?

+0

Ziemlich gute Frage gefunden werden. Ich denke nicht, dass es möglich ist, aber lass uns abwarten. – jfar

Antwort

7

Es ist möglich, jede beliebige LINQ-Abfrage in eine SqlDependency einzubetten, einschließlich EF Linq-Abfragen, siehe LinqToCache. Aber unglücklicherweise ist die Art und Weise, wie EF das SQL für die Abfragen formuliert, sogar das einfachste from t in context.table select t, mit der Einschränkung der Abfragebenachrichtigung nicht kompatibel, und die SqlDependency wird sofort als ungültige Anweisung ungültig gemacht. Ich habe darüber in SqlDependency based caching of LINQ Queries gesprochen.

Was Sie tun können, ist SqlChangeMonitor mit einfachen SqlCommand Objekte als einfache SELECT ... FROM Table auf Ihre Tabellen, die wahrscheinlich zu ändern sind. Sie müssen wissen, dass zwischen den Kosten für die Einrichtung von Benachrichtigungen und den Kosten für die Abfrage ein Gleichgewicht besteht. Wenn sich Ihre Tabellen häufig ändern, kann die Überwachung auf Änderungen teurer sein als die Abfrage. Sehen Sie diesen Artikel The Mysterious Notification, um zu verstehen, wie QN funktioniert und was die Kosten der Überwachung sind.

+0

In diesem speziellen Fall ändern sich die Daten sehr selten (10-20 Datensätze pro Woche aktualisiert), aber dies ist ein Lernprojekt und ich würde gerne verstehen, wie man "das Richtige tut" in einer sich stärker verändernden Umgebung - wird folgen Deine Links. Vielen Dank. –

+0

Zwischenspeichern der 'Daten-Abruf' ist der Schlüssel, es dauert ~ 3 Sekunden, um die Tausende von Aufzeichnungen zu verarbeiten - obwohl ich einige Zeit Optimierung verbringen könnte, wird es immer noch nicht schnell sein - während wegen der langsamen Änderungsrate, Caching der Daten wird selten abgelaufen sein! –