Sometimes you want to able to save data that is not a page or a content block. Examples could be data like comments created by visitors or orders in your webshop. An easy way to save such data is using EPiServers build-in Dynamic Data Store.
There are a lot of blogs online about this subject. Unfortunality most of them only work in EPiServer 6. In this blog I took a look at Ted Nyberg’s blog Introduction to EPiServer Dynamic Data Store (DDS) but rewrote it so that it now works for EPiServer 7.5.
I am going to store comments created by my visitors using a Dynamic Data Store. First we need a model to hold the data. Create your model in the ~/Models/DynamicDatadirectory or any directory you prefer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Comment : IDynamicData { // Required to implement IDynamicData public Identity Id { get; set; } // Save datetime comment was created public DateTime DateTime { get; set; } // Save pageID of page on which comment was created. public int PageID { get; set; } // Save name of person who commented public string Name { get; set; } // Holds the actual comment public string Text { get; set; } } |
This model is not complete yet! But it summarizes the data I like to store. What is important here is that your model inherits from IDynamicData and that you have put some references in your code to EPiServer.Data and EPiServer.Data.Dynamic.
You can put whatever property you want in your model. But the Identity Id property is required to identify this comment in the store.
Now lets create a contructor and some initialisation methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
protected void Initialize() { this.Id = Identity.NewIdentity(Guid.NewGuid()); this.DateTime = DateTime.Now; this.Name = string.Empty; this.Text = string.Empty; } public Comment() { Initialize(); } public Comment(int pageId, string name, string text) { this.PageID = pageId; this.Name = name; this.Text = text; } |
ote that a public, parameter-less constructor is required to support serialization to the Dynamic Data Store (Ted Nyberg)
Next lets make some methods that saves, deletes and retrieves comments.
1 2 3 4 5 6 7 8 9 10 11 |
/// <summary> /// Saves comment to Dynamic Data Store /// </summary> public void Save() { // Create a data store (but only if one doesn't exist, we won't overwrite an existing one) var store = DynamicDataStoreFactory.Instance.CreateStore(typeof (Comment)); // Save the current comment store.Save(this); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// <summary> /// Delete the comment permanently /// </summary> /// <param name="comment"></param> public static void Delete(Comment comment) { // Create a data store (but only if one doesn't exist, we won't overwrite an existing one) var store = DynamicDataStoreFactory.Instance.CreateStore(typeof(Comment)); // Delete the specified comment store.Delete(comment.Id); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static List<Comment> GetComments(PageReference pageLink) { // Get data store for comments var store = DynamicDataStoreFactory.Instance.CreateStore(typeof(Comment)); // Retrieve comments var comments = store.Items<Comment>().Where(x => x.PageID == pageLink.ID); if (comments == null) return new List<Comment>(); //return comments as List<Comment>; return comments.ToList(); } |
Notice that I use DynamicDataStoreFactory to create a store. Also retrieving comments is done differently.
Ok thats it. Now we can save comments with this code:
1 2 |
var comment = new Comment(currentPage.PageLink.ID, "Rowan", "This is my first comment! Hello world!"); comment.Save(); |
And retrieving comments is as easy as saving them:
1 |
var comments = Comment.GetComments(currentPage.PageLink); |
Changing or updating your Dynamic Data Store model
So what happens when you update your comment model. For example you add an extra property email address that stores the email address of the visitor who added the comment. If you do that and rebuild the project and try to retrieve the comments you will get an error:
To solve this you need to remap your Dynamic Data Store. This can be done automatically everytime you change your model using the attribute:
[EPiServerDataStore(AutomaticallyRemapStore = true)]
Be carefull! Remapping can lead to data loss.
Other attributes that could be handy are:
[EPiServerDataStore(AutomaticallyCreateStore = true)]
Setting this boolean property to true means that you no longer need to worry if your store exists or not, it will be created on demand when GetStore is called!