smithsson68@gmail.com
May 10, 2010
  7661
(0 votes)

Data Container Indifference in the Dynamic Data Store

The Dynamic Data Store (DDS) that shipped with EPiServer CMS 6 has a feature unofficially called “Data Container Indifference”. This is a feature that some people are going to love, and some hate.

Let me explain what I’m talking about. When a .NET object is saved to the DDS the object is reflected over and it’s public properties are extracted and mapped to a column in the database. The CLR Type of the object saved is saved but it is important to note that the DDS does not use serialization in the same way as, let’s say, the BinaryFormatter class in the .NET class library. What this essentially means is that the .NET object instance saved translates to a set of name value property pairs.

So where does the data container indifference come in then?

The DynamicDataStore class has 3 method groups for reading data from a store.

Methods that return instances of System.Object:

public abstract Object Load(Identity id);
public abstract IEnumerable<Object> LoadAll();
public abstract IEnumerable<Object> Find(string propertyName, object value);
public abstract IEnumerable<Object> Find(IDictionary<string, object> parameters);
public abstract IOrderedQueryable<Object> Items();

Methods that return instances of TResult:

public abstract TResult Load<TResult>(Identity id);
public abstract IEnumerable<TResult> LoadAll<TResult>();
public abstract IEnumerable<TResult> Find<TResult>(string propertyName, object value);
public abstract IEnumerable<TResult> Find<TResult>(IDictionary<string, object> parameters);
public abstract IOrderedQueryable<TResult> Items<TResult>();

Methods that return instance of EPiServer.Data.Dynamic.PropertyBag:

public abstract PropertyBag LoadAsPropertyBag(Identity id);
public abstract IEnumerable<PropertyBag> LoadAllAsPropertyBag();
public abstract IEnumerable<PropertyBag> FindAsPropertyBag(IDictionary<string, object> parameters);
public abstract IEnumerable<PropertyBag> FindAsPropertyBag(string propertyName, object value);
public abstract IOrderedQueryable<PropertyBag> ItemsAsPropertyBag();

This means that data saved to the DDS can be read back using any of the 3 method groups regardless of the CLR Type of the actual .NET object instance that was saved.

Some examples should help visualize what I’m talking about. Take the following class:

   1:   public class Person
   2:   {
   3:       public string FirstName { get; set; }
   4:       public string LastName { get; set; }
   5:       public DateTime DateOfBirth { get; set; }
   6:   }
 

Create a store in the DDS using the Person class as the definition for the store:

   1:  // Create the factory and the store
   2:  EPiServerDynamicDataStoreFactory factory = new EPiServerDynamicDataStoreFactory();
   3:   
   4:  // The definition of the store will be defined by the Person class
   5:  // i.e. it will have 3 properties, FirstName, LastName and DateOfBirth
   6:  DynamicDataStore store = factory.CreateStore(typeof(Person));
   7:   
   8:  // Save an instance of person
   9:  Person p = new Person()
  10:  {
  11:      FirstName = "John",
  12:      LastName = "Doe",
  13:      DateOfBirth = new DateTime(1972, 4, 21)
  14:  };
  15:   
  16:  store.Save(p);

As you would expect you can then read the person back using the following code:

   1:  // Read the person back using a Person class as the container
   2:  Person p2 = store.Find<Person>("LastName", "Doe").FirstOrDefault();

However, what you can also do is read the person back into a PropertyBag:

   1:  // Read the person back using a PropertyBag
   2:  PropertyBag bag = store.FindAsPropertyBag("LastName", "Doe").FirstOrDefault();

But even more surprising is that you can read it back with a completely different class:

class Person2
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public char Gender { get; set; }
}
 
   1:  // Read the person back using a Person2 class as the container
   2:  Person2 person2 = store.Find<Person2>("LastName", "Doe").FirstOrDefault();

What is happening here is that the stored properties are read into memory and then the DDS will map them against any matching properties (with same name and value type) on the Person2 class. In the above case FirstName, LastName and DateOfBirth will be successfully mapped but Gender will not and therefore have a default value for the CLR Type.

This mechanism could potentially be used as some kind of runtime polymorphism and even allows you to completely replace an entire class without affecting the data stored in the DDS.

The group of methods that return System.Object will always return an instance of the CLR Type that was actually used to save the properties to the DDS, in this case a Person class.

The source code for this example can be found here.

May 10, 2010

Comments

Please login to comment.
Latest blogs
AEO, GEO and SEO with Epicweb AI Assistant in Optimizely CMS

Traditional SEO remains important, but content must now also be optimized for answer engines and generative AI. This article explains how the Epicw...

Luc Gosso (MVP) | May 11, 2026 |

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

How Niteco's Upgrade Machine   uses orchestrated AI coding agents to deliver a buildable baseline and a running CMS, then hands over for...

Hung Le Hoang | May 11, 2026

Commerce 15 and CMS 13: Optimizely’s Next Step Toward AI-Powered, Graph-First Commerce

Optimizely is preparing to release Commerce 15 in mid-May 2026 , positioning this as a foundational shift—not just an upgrade. The direction is...

Augusto Davalos | May 7, 2026

The future of Content: Introducing Optimizely CMS 13

Optimizely In the rapidly evolving landscape of digital experience, the "monolithic vs. headless" debate is being replaced by a more sophisticated...

Aniket | May 6, 2026

Hide built in scheduled job from the admin UI

Ok so this probably goes into the not so useful section but late last night I got a veery strong feeling that all projects I am  involved with have...

Per Nergård (MVP) | May 6, 2026

Optimizely CMS 11 Is Out of Support — and the Hard Part of the Upgrade Isn't the CMS

On 10 April 2026, Optimizely formally announced that CMS 11 was out of support — CMS 13 had reached GA on 31 March, and by policy only the two most...

Allan Thraen | May 6, 2026 |