Dynamic Data Store
Optimizely Dynamic Data Store (DDS) saves, loads, and searches compile-time data types (.NET object instances) and run-time data types (property bags) in shared tables in SQL Server.
Optimizely Dynamic Data Store (DDS) is an Object-Relational Mapper (ORM). It provides an API for saving, loading, and searching data in SQL Server. Use DDS to persist simple data structures without creating custom database tables. DDS ships as part of the Framework package.
When used with compile-time data types (.NET classes), properties with a public getter and a setter (the setter does not need to be public) are mapped to a column in a database table. For runtime data types, each property added to a PropertyBag is mapped in the same way.
DDS has the following advantages:
- Straightforward to use for simple data structures.
- Supports LINQ for querying data.
- Does not require custom tables, which simplifies upgrades and installations.
- Supports multiple database tables to isolate stores.
- Supports typed models and property bags.
- Includes a cache layer.
Avoid DDS for high-performance and high-scalability requirements or when storing large object graphs (for example, DDS does not support lazy loading). In these situations, store data in custom tables where the table design and API are optimized for a specific use case. Alternative technologies for SQL Server include Microsoft Entity Framework and NHibernate for .NET.
DDS data type mapping
DDS maps data types to columns in a single database table. Understanding how mapping works helps you design data structures that store and retrieve efficiently.
The table contains multiple columns of each supported data type. When a data structure is saved, DDS maps the .NET CLR type of each property against an internal list of supported types.
DDS supports the following types of mapping:
Inline mapping
Inline mapping maps a property of a class or PropertyBag directly to one of the supported database columns. The following types support inline mapping:
System.Byte(and arrays of)System.Int16System.Int32System.Int64System.EnumSystem.SingleSystem.DoubleSystem.DateTimeSystem.StringSystem.Char(and arrays of)System.BooleanSystem.GuidEPiServer.Data.Identity
Collection mapping
A property is mapped as a collection if it implements the System.IEnumerable interface. Collection elements (keys and values for System.IDictionary) are stored in a special reference table.
Although EPiServer.Data.Dynamic.PropertyBag implements System.IEnumerable, DDS treats it as a reference type (see the following section).
Reference mapping
Properties that cannot be mapped inline or as a collection (including EPiServer.Data.Dynamic.PropertyBag) are mapped as references. Their properties are mapped as a subtype, and a link row in the reference table connects the parent data structure to the child. This approach lets you save complex trees of data structures (object graphs) in DDS.
Default table
The default DDS table is tblBigTable. It contains the following fixed (mandatory) columns:
pkId– The store ID and primary key of each data structure stored.Row– The row index. Each structure may span one or more rows in the big table.StoreName– The store name to which the data structure belongs.ItemType– The .NET CLR Type that contains the properties saved to the current row.
The default big table also contains the following optional columns:
BooleanXX(where XX is 01 through to 05) x 5IntegerXX(where XX is 01 through to 10) x 10LongXX(where XX is 01 through to 05) x 5DateTimeXX(where XX is 01 through to 05) x 5GuidXX(where XX is 01 through to 03) x 3FloatXX(where XX is 01 through to 07) x 7StringXX(where XX is 01 through to 10) x 10BinaryXX(where XX is 01 through to 05) x 5Indexed_Boolean01Indexed_IntegerXX(where XX is 01 through to 03) x 3Indexed_LongXX(where XX is 01 through to 02) x 2Indexed_DateTime01Indexed_Guid01Indexed_FloatXX(where XX is 01 through to 03) x 3Indexed_StringXX(where XX is 01 through to 03) x 3Indexed_Binary01(not Oracle)
The columns whose names start with Indexed have database indexes created on them.
Add or remove columns in this table to suit the type of data you are saving. For example, if a data type contains more than ten strings, the eleventh through twentieth strings are stored in a second row. This causes a join at runtime when reading the data. Adding String11, String12, and so on to the big table reduces row overspill and increases performance. To add more indexes, create columns with names starting with Indexed and add a database index on each.
Custom tables
Create a custom table when a data type benefits from a tailored column layout. For example, a type that contains only strings performs better in a dedicated table. Include the mandatory columns (pkId, Row, StoreName, ItemType) and add up to about 20 StringXX columns.
To use a custom table, add the EPiServerDataTableAttribute to your class and set the TableName property to the name of the custom table.
SQL Server type mapping
The following table lists the database column types in the default big table and the .NET CLR inline types they map to:
| Database Column Type | .NET CLR “Inline” Types |
|---|---|
varbinary(max)varbinary(900) | System.Byte[] |
int | System.Byte, System.Int16, System.Int32, System.Enum |
bigint | System.Int64 |
float | System.Single, System.Double |
datetime | System.DateTime |
uniqueidentifier | System.Guid |
nvarchar(max)nvarchar(450) | System.String, System.Char, System.Char[], EpiServer.Data.Identity |
bit | System.Boolean |
Database views
Each store is represented in the database by a view. Use these views like any other database view, including cross-joining with other tables and views.
Assembly and namespaces
All DDS classes reside in the EPiServer.Data assembly. Reference the appropriate namespace for the functionality you need.
The EPiServer.Data assembly contains the following main namespaces:
EPiServer.Data– Contains core classes used in DDS, most notably theIdentityclass.EPiServer.Data.Configuration– Contains the configuration classes for DDS.EPiServer.Data.Dynamic– Contains theDynamicDataStoreFactoryandDynamicDataStoreclasses and their support classes.
Store management
Use the DynamicDataStoreFactory class to create, obtain, and delete stores. Access the singleton instance through the static Instance property. Alternatively, decorate .NET classes with EPiServerDataStoreAttribute and set AutomaticallyCreateStore to true to create stores automatically.
Save and load data
Save and load data using compile-time data types (.NET classes) or runtime data types with the EPiServer.Data.Dynamic.PropertyBag class. DDS is divided into logical stores identified by name. Stores are not polymorphic: only one property set is saved per store. However, re-mapping stores through interfaces and template types provides a level of polymorphism.
Search data
Search data in DDS using the following methods:
- Simple Find method – Find data structures by matching one or more name-value pairs with data in the store.
- LINQ – Use Microsoft Language Integrated Query technology to find data structures.
Updated 19 days ago
