How to migrate from uCommerce to EPiServer Commerce part 1: data models and enums
This article is following the introduction article I wrote previously https://world.episerver.com/blogs/giuliano-dore/dates/2021/2/how-to-migrate-from-ucommerce-to-episerver-commerce-part-0-skus-and-tree-structure/ regarding migration from uCommerce to EPiServer Commerce. If you are looking for info about tree structure and skus in uCommerce check this out!
Product properties migration
If you are familiar with CMS where editors can set the definitions for templates, you know that it can be tricky to migrate to CMS where developers are setting definitions for templates like EPiServer.
What does it mean?
It is possible to describe EPiServer as a code-first modelling CMS: the developers (aka the people who have access to the codebase) can create, update and delete pages and products templates by reading and updating code.
If I want to create a page template in EPiServer – like a landing page – I need to create a LandingPage class that inherits from PageData and set some properties inside that class for the properties that I want for the page. If I want a property for the body of the page as html content, I then need to create a public XhtmlString property like this:
public virtual XhtmlString Content { get; set; }
And EPiServer is smart enough to associate this property in that class with a property in a “landing page” template.
Unfortunately, some CMS also work the other way around: editors can log into the backoffice and define pages and properties through the backoffice. Once the properties, pages & products have been defined, the developers start writing / generating code to map the definitions that they created in order to add business logic for their projects.
I would call this approach ‘template-first’. Umbraco, Sitecore and uCommerce use template-first data modelling.
Is code-first better or worse than template first? I think both solutions have pros and cons. Feel free to add a comment below regarding the question 😊
Coming back to uCommerce, how can we migrate data & data models from a template-first project to code-first project?
Regarding this task, we have some good news and some bad news.
The good news is that the data types are often easy to match: properties like simple text, html, numbers are easy to “translate” from one data model to another one. Some examples are available below:
uCommerce property data type |
EPiServer Commerce property data type |
Boolean |
C# boolean |
ShortText |
C# string |
RichText |
C# XhtmlString |
The bad news is that, while it is possible to automate the data migration, it is not possible to automate the data model migration.
As mentioned previously, EPiServer data model depends on code. While we can retrieve the products definitions from the uCommerce database, we would need to generate code on the fly and add it to the project in order to automatically migrate products definitions and data in the same thread.
While it is possible, I find that this solution is extremely complex and possibly over-engineered for very little value.
The solution we found was to manually provide data definitions instead of trying to automatically get the definitions and the data in the same thread:
- Based on the definitions we can find in uCommerce, we manually “translate” the products and properties definitions to EPiServer Commerce using c# classes.
- Once all the definitions are available, we start running a scheduled job to migrate data from uCommerce to EPiServer Commerce using the templates we created during step 1.
Why is it so important to have all the definitions ready before step 2? The reason is that, if we are attempting to migrate data with missing definitions, there will be data loss. As we are trying to avoid data loss, we must make sure all the definitions are ready before starting the second step.
Enum data migrations
It isn’t uncommon for products to have properties where the value is available as one choice out of a predefined list. An example would be a scenario where we would want to create a ‘Colour’ property but we would want to offer only options like white, blue, orange, etc.
This can be achieved in uCommerce using Enum data types. Editors can setup Enums inside the Commerce Settings section under the ‘data types’ sub-section:
As you can see, editors can create enum data types and they can also define the potential values to select from. They can add / update / delete values under the enum definition that they just created without breaking their e-commerce website.
One issue here is that Enum values in EPiServer are inside the code. EPiServer developers can define “enum” properties in c# but, due to the nature of code-first data-modelling, it is not possible to allow editors to update enums in c#. The other issue here is that any update from a developer would require code deployment.
In short: c# Enums are not a good fit for uCommerce Enum data types.
We started looking for alternative data models where editors could update the list of pre-defined values. We found that we could use the CMS content tree and SelectionFactories to “simulate” a “editor friendly” enum property in EPiServer:
- Inside EPiServer CMS, we would set a “repository” page as “folder”.
- The repository page would allow children nodes.
- Each children node would contain a simple text property.
- On pages where we would expect the “Enum” property type, we would instead have a simple string property with a [SelectOne] attribute using a SelectionFactory to retrieve the children’s nodes of our “repository” page.
Our content tree would look like this:
- MyWebsite
- Generic page
- Login page
- FAQ page
- Colour repository (not a real page)
- Green
- Blue
- Black
And our SelectionFactory would look like this:
public class ProductColourSelectionFactory : ISelectionFactory
{
private Injected<ISiteRepositoryService> siteRepositoryService;
public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
//this service would find the relevant repository folder for the "enum" we are trying to simulate
//and list all the children nodes
return siteRepositoryService.Service.GetRepositoryPages(x => x.ProductColourRepository)
.Select(x => new SelectItem
{
Text = x.DisplayNameValue,
Value = x.ContentLink
});
}
}
The final result inside EPiServer commerce would look like this:
Once our control is available, the last step is to make sure that the migration script will assign the right value to the Color property and that the dropdown control will display the accurate value.
That's it for today, I hope it was helpful. If you have tips regarding data models or data migrations, feel free to drop a comment below 😊
Comments