Anders Hattestad
May 25, 2012
  4866
(2 votes)

Cache Dynamic Data Store items

When I use DDS I always use a pattern where I have a public static Items implementation that I can do my query against. This logic is placed inside a common class all my DDS tables inherit from

Code Snippet
  1. public class BaseData<T> : IDynamicData, ISaveMe where T : BaseData<T>, new()
  2. {
  3.     public EPiServer.Data.Identity Id { get; set; }
  4.     public static IOrderedQueryable<T> Items
  5.     {
  6.         get
  7.         {
  8.             return Store.Items<T>();
  9.  
  10.         }
  11.     }

So when I needed to speed things up a bit I changed my Items implementation to instead return a memory list with all my items,

Code Snippet
  1. public static IQueryable<T> Items
  2. {
  3.     get
  4.     {
  5.         if (Cache())
  6.             return ItemsMemory;
  7.  
  8.         return Store.Items<T>();
  9.  
  10.     }
  11. }
  12.  
  13. public static bool Cache()
  14. {
  15.     string tmp = System.Web.Configuration.WebConfigurationManager.AppSettings.Get("Cache_"+typeof(T).Name);
  16.     if (!string.IsNullOrEmpty(tmp))
  17.         return true;
  18.     return false;
  19. }
  20.  
  21. static IQueryable<T> ItemsMemory
  22. {
  23.     get
  24.     {
  25.         if (_itemsMemory == null)
  26.         {
  27.             WriteNewCacheData();
  28.         }
  29.         return _itemsMemory.AsQueryable();
  30.     }
  31. }
  32. static List<T> _itemsMemory = null;
  33. static object lockObject = new object();
  34. static DateTime _lastCleard = DateTime.MinValue;
  35. public static void WriteNewCacheData()
  36. {
  37.     if (Cache())
  38.     {
  39.         WriteNewCacheData((from item2 in Store.Items<T>() select item2).ToList());
  40.     }
  41. }
  42. static void WriteNewCacheData(List<T> data)
  43. {
  44.     lock (lockObject)
  45.     {
  46.         _lastCleard = DateTime.Now;
  47.         _itemsMemory = data;
  48.     }
  49. }

Since all my DDS classes inherits from the same base, I made my change so I could turn on memory cache using appsettings.

When I retrieve a object and want to make a change to I just make the change and save it using my LazyDDSSave class. Even before the item is saved all new querys will access the changed object since it’s the same object. One could make a CreateWritebleClone implementation update the cache when one have done the save, but I didn’t.

Its only when we create a new object or delete a object we need to change the number of elements in the memory cache.

Code Snippet
  1. public virtual void Save()
  2. {
  3.     LazyDSSSave.Current.AddToSave(this);
  4. }
  5. public static void Save(T item)
  6. {
  7.     LazyDSSSave.Current.AddToSave(item);
  8. }
  9. public static void Delete(T item)
  10. {
  11.     Store.Delete(item);
  12.     if (Cache())
  13.     {
  14.         WriteNewCacheData((from item2 in Store.Items<T>() select item2).ToList());
  15.     }
  16. }
  17. public void SaveMe()
  18. {
  19.     Store.Save(this);
  20.     if (Cache())
  21.     {
  22.         var list = (_itemsMemory as List<T>);
  23.         if (list != null)
  24.             if (list.IndexOf(this as T) == -1)
  25.             {
  26.                 WriteNewCacheData((from item in Store.Items<T>() select item).ToList());
  27.             }
  28.     }
  29. }

I have selected a full reread from the data store when I delete or add a new item, but this could also be changed to just add or delete the object from the memory list.

If you are in a enterprise load balance server situation  one could either implement a event based reload or one could reload the memory list after a fixed amount of time.

I gain a lot performance by just using my implementation above in a project I worked on. I had many updates on objects, and not very many delete or new ones.

Since I then cache all my DDS tables (or most of them) I don’t need to cache my results from query's against my DDS tables So when updates are done I don’t need to invalidate my aggregate cache. That saves me a lot of worries Smile.

Have uploaded the base class in the code section here

May 25, 2012

Comments

May 28, 2012 08:12 AM

I have a similar setup when working with DDS.
Great inspiration how to improve it - Thanks!

Please login to comment.
Latest blogs
Optimizely Opal: How to Build Effective Workflow Agents

If you're building workflow agents in Optimizely Opal, this post covers how specialized agents pass context to each other, why keeping agents small...

Andre | May 20, 2026

ReviewPR: An Azure Function That Reviews Your Azure DevOps Pull Requests With Claude

A while back I wrote about an  Azure Function App for PDF creation that we use to offload PDF rendering from our Optimizely DXP site. That same...

KennyG | May 19, 2026

Accelerating Optimizely CMS and Commerce upgrades with agentic AI (Part 2 of 2)

The Real Transformation in Optimizely CMS 13: Why the Upgrade Itself Is the Easy Part. A field-tested playbook for enterprise teams moving from...

Hung Le Hoang | May 18, 2026

Is the most powerful AI model really the best value?

Artificial Intelligence is already becoming part of everyday software development. Developers now use AI tools to generate code, write documentatio...

K Khan | May 16, 2026

Optimizely London Dev Meetup 2026

Well, everyone, it's that time of the year again, and we have another London Developer meet up coming for this summer. The date is set for the 2nd ...

Scott Reed | May 15, 2026

Semantic Search - Deep Dive

Deep dive into semantic search with Optimizely Graph

Michał Mitas | May 14, 2026 |