As we’ve been working with Sitecore Experience Commerce, we’ve observed what, for Sitecore, is mysterious behaviour in Commerce entity SitecoreIds. If you create a new item in a Commerce catalogue, the SitecoreId that is generated for that item, and the one that it will be assigned in the Sitecore tree, will always be identical. You can delete the item and recreate it or move it around in the catalogue as many times as you like and as long as the ID is the same in the catalogue, e.g. Entity-SellableItem-132, it will always have the same SitecoreId: ea901388-c5e8-2e64-f1bb-78e098186fcc.

Below is part of the json that is persisted to the database for the entity showing the ID and the SitecoreId.

{
    "$type": "Sitecore.Commerce.Plugin.Catalog.SellableItem, Sitecore.Commerce.Plugin.Catalog",
    "ProductId": "132",
    "Description": "",
    "Brand": "",
    "Manufacturer": "",
    "TypeOfGood": "",
    "FriendlyId": "132",
    "Id": "Entity-SellableItem-132",
    "Tags":
    {
        "$type": "System.Collections.Generic.List`1[[Sitecore.Commerce.Core.Tag, Sitecore.Commerce.Core]], mscorlib",
        "$values": []
    },
    "SitecoreId": "ea901388-c5e8-2e64-f1bb-78e098186fcc"
}

For anyone who has worked with Sitecore for a while, this seems like some kind of black magic. We are used to GUIDs being completely unpredictable, and in most cases, this is exactly the behaviour that we desire to avoid ID conflicts.

So to the nuts and bolts of it, how is Sitecore Commerce doing this?

I did a quick search and using dotPeek, I found the following class in Sitecore.Commerce.Plugin.Catalog.dll

namespace Sitecore.Commerce.Plugin.Catalog
{
  public static class GuidUtils
  {
    public static Guid GetDeterministicGuid(string input)
    {
      return new Guid(new MD5CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(input)));
    }

    public static string GetDeterministicGuidString(string input)
    {
      return GuidUtils.GetDeterministicGuid(input).ToString();
    }
  }
}

I copied and pasted that class into Linqpad and ran some queries which showed that the IDs generated are always the same for the same input string (deterministic), and I was able to match the GUIDs in the database by entering the same entity ID as the input.

The next question is: why does it behave this way? It makes sense that Commerce can do this because entity IDs in Commerce are unique, therefore there two entities will never generate the same GUID using the code above. My best guess is that it cuts down on churn of items in the Sitecore tree, by reusing the same item, rather than having delete and create a new one. Let me know if you have any other thoughts.

So now you know. And knowing is half the battle.