How to manage existing Sitecore Commerce Entities while refactoring
July 15th 2021
Regular Code Refactoring is an inevitable Step in every project/product lifecycle.
As developers and development techniques evolve, code that you wrote a year ago (Sometimes less), becomes obsolete and technical debt grows, if you don't refactor it from time to time.
I was recently going through a Sitecore Commerce Upgrade and used this opportunity to do some refactoring, which involved -amongst other things- moving some Commerce Components around.
This refactoring can be tricky and cause issues if not handled properly. Since all Commerce Entities are stored is SQL Server as JSON fields, if you rename, or move a component from its original namespace, the entity won't deserialize properly.
There are surely many ways to overcome this issue, but I wanted to share what worked for me, in case you find yourself in the same situation.
My approach was the following:
Keep the legacy components until the component migration process is done.
Build a custom API Endpoint that will scan all Entities having legacy component and replace them with new ones.
Run the API from Postman.
Run queries in DB to make sure there are no leftovers.
Delete Legacy Components
Here's an example of the logic used to remove a component from all Customer Entities:
var customers = await this._commerceCommander.Pipeline<IFindEntitiesInListPipeline>()
.Run(new FindEntitiesInListArgument(typeof(Customer), "customers", 0, int.MaxValue), context);
foreach (var customer in customers.List.Items)
{
if (customer.HasComponent(typeof(SomeLegacyComponent)))
{
customer.RemoveComponent(typeof(SomeLegacyComponent));
}
await this._commerceCommander.Pipeline<IPersistEntityPipeline>()
.Run(new PersistEntityArgument(customer), context);
}
Here's an example of the logic used to replace a component from all Order Entities:
var orders = await this._commerceCommander.Pipeline<IFindEntitiesInListPipeline>()
.Run(new FindEntitiesInListArgument(typeof(Order), "orders", 0, int.MaxValue), context);
foreach (var commerceEntity in orders.List.Items)
{
if (order.HasComponent<SomeLegacyComponent>())
{
order.SetComponent(order.GetComponent<SomeLegacyComponent>().ConvertToNewType());
order.RemoveComponent(typeof(SomeLegacyComponent));
}
}
P.S: ConvertToNewType() is a method I created to convert the old legacy component to the new one.
This approach helped me achieve my refactoring and cleanup legacy components efficiently.
I hope you find this post helpful if you find yourself in a similar situation.
Feel free to leave comments or questions.
Comments