If you have done any customization of the Sitecore commerce engine (9 or 8.2.1) you would have noticed that you look up entities such as orders using the entity id (e.g. order id) using code like this…

findEntityPipeline.Run(new FindEntityArgument(typeof(Order), "ORDER001"), context).Result as Order

This is okay 95% of the time but what about the other 5% of the time?

For instance, what if you need to lookup an order based on its payment transaction id which is on a related entity or component?

If you think about it from a relational database perspective it would be like doing a “where” clause with a “join”, pseudo code example…

select OrderId from order inner join payment on order.orderid = payment.orderid where transactionid = "TRANS0001"

If you are familiar with any of the popular ORMs such as Entity Framework or NHibernate, often, at a database level, they will create a new table that relates two entities together. These relation tables often just have the two fields which hold the relationship between the two tables, we mimic this here.

The following steps outline a way of creating a “Linking entity” to create an “Alternate key” for looking up a order by payment transaction id.  I’m sure there are other ways to do this but this approach is pretty performant as the link entity is indexed by the DB and looked up by the primary key.

We will complete the following steps :-

  1. Create a new “Link entity” to hold a link between the order and the payment transaction.
  2. Add code to create the instance of the link entity.
  3. Detail on how to lookup the order by the transaction id.

Step 1 – Create new Link Entity

  • Open the Sitecore Commerce Engine SDK solution “Customer.Sample.Solution”
  • In the adventure works plugin, create a new folder called “Entities”.
  • Add the following new class

Step 2 – Add code to create the link

Here we will add in a new pipeline block within the create order process to save an instance of our new link entity after the payment is applied to the order. If you were setting up a new link outside of this example, you will need to add code to correct pipelines to ensure the link is created.

  • In the adventure works plugin, navigate to the pipelines > blocks folder.
  • Add the following new class


namespace Sitecore.Commerce.Plugin.AdventureWorks
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Sitecore.Commerce.Core;
using Sitecore.Commerce.Plugin.Carts;
using Sitecore.Commerce.Plugin.Orders;
using Sitecore.Framework.Conditions;
using Sitecore.Framework.Pipelines;
using Payments;
using Entities;
[PipelineDisplayName("PersistTransactionOrderLinkBlock")]
public class PersistTransactionOrderLinkBlock : PipelineBlock<Order, Order, CommercePipelineExecutionContext>
{
/// <summary>
/// The find entity pipeline
/// </summary>
private readonly IFindEntityPipeline findEntityPipeline;
/// <summary>
/// The _persist entity pipeline.
/// </summary>
private readonly IPersistEntityPipeline persistEntityPipeline;
/// <summary>
/// Initializes a new instance of the <see cref="UpdateCouponUsageBlock"/> class.
/// </summary>
/// <param name="findEntityPipeline">
/// The find entity pipeline.
/// </param>
/// <param name="persistEntityPipeline">
/// The persist Entity Pipeline.
/// </param>
public PersistTransactionOrderLinkBlock(IFindEntityPipeline findEntityPipeline, IPersistEntityPipeline persistEntityPipeline)
{
this.findEntityPipeline = findEntityPipeline;
this.persistEntityPipeline = persistEntityPipeline;
}
/// <summary>
/// The run.
/// </summary>
/// <param name="order">
/// The order.
/// </param>
/// <param name="context">
/// The context.
/// </param>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
public override async Task<Order> Run(Order order, CommercePipelineExecutionContext context)
{
var payment = order.GetComponent<FederatedPaymentComponent>();
var link = new TransactionIdToOrderLink(payment.TransactionId, order.Id);
var returnedLink = await persistEntityPipeline.Run(new PersistEntityArgument(link), context);
//Here is how to get the order from somewhere else in code by transactionid
var foundLink = findEntityPipeline.Run(new FindEntityArgument(typeof(TransactionIdToOrderLink), payment.TransactionId), context).Result as TransactionIdToOrderLink;
var foundOrder = findEntityPipeline.Run(new FindEntityArgument(typeof(Order), foundLink.OrderId), context).Result as Order;
return order;
}
}
}

  • Modify ConfigureSitecore.cs to ensure the engine executes the code above in the create order pipeline. Add the following line of code

.ConfigurePipeline<ICreateOrderPipeline>(d => d.Add<PersistTransactionOrderLinkBlock>().After<IPersistOrderPipeline>())

Step 3 – Description on how to lookup the entity else where

Lines 67 and 68 in the “PersistTransactionOrderLinkBlock” class in the code above have been added as an example of how you can use the new link entity to find the order by transaction id in code.

Essentially it is the exact same process as looking up the order entity by order id, the difference being that you go through the link entity first e.g this finds the link entity by payment transaction id then finds the order…

var foundLink = findEntityPipeline.Run(new FindEntityArgument(typeof(TransactionIdToOrderLink), payment.TransactionId), context).Result as TransactionIdToOrderLink;
var foundOrder = findEntityPipeline.Run(new FindEntityArgument(typeof(Order), foundLink.OrderId), context).Result as Order;