🌐 Website Implementation
Dynamic Data Store
📖 Docs

Dynamic Data Store (DDS) - Optimizely CMS 12

Exam Area: Content Area 3 – Website Implementation & Delivery (25%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/dynamic-data-store


1. What is the Dynamic Data Store?

Dynamic Data Store (DDS) is a mechanism for storing custom data in the CMS database without needing to create custom SQL tables.

When to use DDS:

When not to use DDS:


2. Declaring a DDS Store

using EPiServer.Data;
using EPiServer.Data.Dynamic;

// POCO class to store in DDS
[EPiServerDataStore(AutomaticallyRemapStore = true)]
[EPiServerDataTable(TableName = "tblMyData")]  // Optional
public class MySettings
{
    [EPiServerDataIndex]
    public Identity Id { get; set; }    // DDS Identity (required)
    
    public string Name { get; set; }
    public int Value { get; set; }
    public DateTime CreatedDate { get; set; }
    public bool IsActive { get; set; }
}

3. CRUD Operations with DDS

using EPiServer.Data.Dynamic;

public class MySettingsService
{
    private readonly DynamicDataStore _store;

    public MySettingsService()
    {
        _store = typeof(MySettings).GetOrCreateStore();
    }

    // CREATE
    public void Save(MySettings settings)
    {
        if (Identity.IsNullOrEmpty(settings.Id))
        {
            settings.Id = Identity.NewIdentity();
        }
        _store.Save(settings);
    }

    // READ - Single
    public MySettings GetById(Identity id)
    {
        return _store.Load<MySettings>(id);
    }

    // READ - All
    public IEnumerable<MySettings> GetAll()
    {
        return _store.LoadAll<MySettings>();
    }

    // READ - By condition
    public MySettings GetByName(string name)
    {
        return _store.Find<MySettings>("Name", name).FirstOrDefault();
    }

    // LINQ support
    public IEnumerable<MySettings> GetActive()
    {
        return _store.Items<MySettings>()
                     .Where(s => s.IsActive)
                     .ToList();
    }

    // UPDATE
    public void Update(MySettings settings)
    {
        _store.Save(settings);  // Save also updates if an Id exists
    }

    // DELETE
    public void Delete(Identity id)
    {
        _store.Delete(id);
    }

    // DELETE - By object
    public void Delete(MySettings settings)
    {
        _store.Delete(settings);
    }
}

4. DDS with Dependency Injection

public class MySettingsService
{
    private readonly DynamicDataStoreFactory _storeFactory;

    public MySettingsService(DynamicDataStoreFactory storeFactory)
    {
        _storeFactory = storeFactory;
    }

    private DynamicDataStore Store => _storeFactory.GetStore(typeof(MySettings))
                                       ?? _storeFactory.CreateStore(typeof(MySettings));

    public MySettings GetSettings()
    {
        return Store.LoadAll<MySettings>().FirstOrDefault();
    }
}

5. Identity Type

// Identity is the ID type used in DDS
Identity id = Identity.NewIdentity();           // Create new
Identity id2 = Identity.NewIdentity(Guid.NewGuid()); // From GUID
bool isEmpty = Identity.IsNullOrEmpty(id);

// Compare
bool equal = id.Equals(id2);
string str = id.ToString();  // GUID string

6. Indexing in DDS

// Add indexes to speed up queries
[EPiServerDataStore]
public class UserPreference
{
    [EPiServerDataIndex]
    public Identity Id { get; set; }
    
    [EPiServerDataIndex]  // Index on this field
    public string UserId { get; set; }
    
    public string PreferenceKey { get; set; }
    public string PreferenceValue { get; set; }
}

7. Custom Database Tables

In addition to DDS, you can create custom tables:

// Use IInitializableModule to create a table
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Data.DataInitialization))]
public class CustomTableInitialization : IInitializableModule
{
    private readonly IDatabaseHandler _databaseHandler;

    public void Initialize(InitializationEngine context)
    {
        CreateCustomTable();
    }

    private void CreateCustomTable()
    {
        const string sql = @"
            IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES 
                           WHERE TABLE_NAME = 'tblCustom')
            BEGIN
                CREATE TABLE tblCustom (
                    Id INT IDENTITY(1,1) PRIMARY KEY,
                    Name NVARCHAR(200) NOT NULL,
                    Value NVARCHAR(MAX),
                    Created DATETIME DEFAULT GETDATE()
                )
            END";
        
        // Execute SQL
    }
}

8. Choosing: DDS vs Custom Table

CriteriaDDSCustom Table
SchemaAutomaticSelf-managed
Query flexibilityLimitedFull SQL
PerformanceModerateBetter
Complex relationsNoYes
Ease of useEasyMore complex

Review Questions

  1. Where does DDS store data? (In the CMS SQL Server database)
  2. Which attribute marks a class for use with DDS? ([EPiServerDataStore])
  3. What is the ID type in DDS? (Identity)
  4. How do you query all items in DDS? (store.LoadAll<T>())
  5. When should you NOT use DDS? (Large data, complex queries, foreign key relationships)