allBlogsList

SXC 9.3.0: How to Persist Commerce Entities, the new way!

How to persist Commerce Entities in SXC 9.3.0 and beyond!

In this article, I will explain the new way of persisting entities in Sitecore Experience Commerce platform introduced in SXC version 9.3.0. It is important to understand the new way as the old way of persisting entities will soon be deprecated in the future versions. Let's dive right into it...

Commerce Entities are essential for Commerce engine applications. As per Sitecore's official documentation, "A commerce entity represents a core unit of persistence in the form of a POCO class that inherits from commerce entity and can extend the entity along with behavior defined based on lifecycle events of the entity or defined commands.".

To name a few which ship out of the box, 

  • Customer
  • Catalog
  • SellableItem
  • Order
  • Cart
  • Promotion
  • Content
  • Pricing
  • Inventory

Based on our client's and customer needs, we always have to extend these entities to store relavant information pertaining to the business requirements. 

There are multiple ways to persist entities when you are processing your logic inside a command or a pipeline block by using IPersistEntityPipeline or CommerceCommander. We will not go through that logic in this article. The intention of this article is to show the new way of persisting entities when you are executing a pipeline and at the end of the pipeline, you want to save/persist your changes to the database.

Let's take an example of how we as developers are used to persist entities before 9.3,

When we add a sellable item (product) to the cart, it triggers the IAddCartLinePipeline pipeline. If you navigate to the NodeConfiguration, you will notice that this pipeline executes a series of blocks which are necessary actions to be taken when an item is added to the cart and at the end of the pipeline, it calls PersistCartBlock to save these changes to the database. This block is responsible for persisting/saving all the changes you applied to the cart in the database.

    -----------------------------------------------------------------
Sitecore.Commerce.Plugin.Carts
IAddCartLinePipeline (Sitecore.Commerce.Plugin.Carts.CartLineArgument => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Catalog.ValidateSellableItemBlock (Sitecore.Commerce.Plugin.Carts.CartLineArgument => Sitecore.Commerce.Plugin.Carts.CartLineArgument)
     ------------------------------------------------------------
     Plugin.Carts.AddCartLineBlock (Sitecore.Commerce.Plugin.Carts.CartLineArgument => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Carts.AddContactBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Carts.IPopulateValidateCartPipeline (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.GiftCards.AddCartLineGiftCardBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.DigitalItems.AddCartLineDigitalProductBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.DigitalItems.AddCartLineWarrantyBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.DigitalItems.AddCartLineInstallationBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Carts.ICalculateCartLinesPipeline (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Carts.ICalculateCartPipeline (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
     ------------------------------------------------------------
     Plugin.Carts.PersistCartBlock (Sitecore.Commerce.Plugin.Carts.Cart => Sitecore.Commerce.Plugin.Carts.Cart)
-----------------------------------------------------------------

Similar to this, there are multiple other ways to persist entities like 

PersistCustomerBlock

PersistSellableItemBlock

PersistOrderBlock

PersistPromotionBlock, etc.,

Coming to SXC 9.3.0, I noticed a warning that PersistOrderBlock will be deprecated in the future versions and the new approach would be a three step process

  • PrepArgumentToPersistEntityBlock<T>
  • IPersistEntityPipeline
  • PostPersistEntityBlock<T>

Let's say, if we want to persist an order, instead of just calling Sitecore.Commerce.Plugin.Orders.PersistOrderBlock as shown in this example below

    -----------------------------------------------------------------
Sitecore.Commerce.Plugin.Orders
IPersistOrderPipeline (Sitecore.Commerce.Plugin.Orders.Order => Sitecore.Commerce.Plugin.Orders.Order)
     ------------------------------------------------------------
     Plugin.Orders.PersistOrderBlock (Sitecore.Commerce.Plugin.Orders.Order => Sitecore.Commerce.Plugin.Orders.Order)
     ------------------------------------------------------------
     Plugin.Orders.PersistOrderByOrderIdIndexBlock (Sitecore.Commerce.Plugin.Orders.Order => Sitecore.Commerce.Plugin.Orders.Order)
-----------------------------------------------------------------

The new approach would be to replace PersistOrderBlock as follows

which would translate to

    -----------------------------------------------------------------
Sitecore.Commerce.Plugin.Orders
IPersistOrderPipeline (Sitecore.Commerce.Plugin.Orders.Order => Sitecore.Commerce.Plugin.Orders.Order)
     ------------------------------------------------------------
     Core.PrepArgumentToPersistEntityBlock`1[Sitecore.Commerce.Plugin.Orders.Order] (Sitecore.Commerce.Plugin.Orders.Order =&gt; Sitecore.Commerce.Core.PersistEntityArgument)
     ------------------------------------------------------------
     Core.IPersistEntityPipeline (Sitecore.Commerce.Core.PersistEntityArgument =&gt; Sitecore.Commerce.Core.PersistEntityArgument)
     ------------------------------------------------------------
     Core.PostPersistEntityBlock`1[Sitecore.Commerce.Plugin.Orders.Order] (Sitecore.Commerce.Core.PersistEntityArgument => Sitecore.Commerce.Plugin.Orders.Order)
     ------------------------------------------------------------
     Plugin.Orders.PersistOrderByOrderIdIndexBlock (Sitecore.Commerce.Plugin.Orders.Order => Sitecore.Commerce.Plugin.Orders.Order)
-----------------------------------------------------------------

Even though the example given is applicable for persisting an order, when I checked the logic using decomplier, it should work for all types of Commerce Entities.

My guess is that eventually all entities will start following this new approach and would highly recommend getting used to this new approach. Please test it thoroughly before applying your changes on production environments.

Additional Information: