The introduction of rollup fields in Microsoft Dynamics 2015 was met with widespread acclaim. No longer was custom code needed in order to sum values on Child records; this can now be handled out-of-the-box via field configuration. However, this isn’t to say that there are not limitations.

Unless the rollup field is manually refreshed or the scheduled recalculation job hits, you could be interacting with “bad” data. Take a look at the following scenario. Two custom entities have been built out, a Parent and a Child, with a 1:N relationship between the Parent and Child entities. A currency “Weekly Allowance” field is on the Child record, with a rollup field on the Parent calculating the Total Weekly Allowance.

 

Notice that when adding a second Child to Parent 1, the Total Weekly Allowances field still displays the previous total. Obviously, this can be resolved by clicking the calculator button next to the field, but this can be problematic when referencing the field in a view where the recalculation option is not present or you are not interacting with the record directly, such as when records are created programmatically.

Luckily, the SDK contains the class “CalculateRollupFieldRequest” that can force the calculation to occur on a specific record without having to wait until the scheduled recalculation job runs. Using this class is as simple as passing in a target EntityReference and the rollup field on the Entity.

Noticing that these are the only two parameters to pass into the constructor, it becomes pretty obvious that we can build the code out as a reusable Custom Workflow Activity, with the InArguments being the current entity’s field that is the lookup to the parent and the parent’s rollup field:

Calling the CWA from a workflow, we pass in the field on the current Child entity as well as the rollup field on the Parent entity:

Activate, and voila! Adding an additional Child shows that it sets the value. Notice that it still says $55 on the form – in order for the change to render on the form, you will still need to refresh/recalculate, but the value has been committed to the database.

The complete code is displayed below for your reference.

 

using System;

using Microsoft.Xrm.Sdk;

using Microsoft.Xrm.Sdk.Workflow;

using System.Activities;

using Microsoft.Xrm.Sdk.Query;

using Microsoft.Crm.Sdk.Messages;

 

namespace ForceRollupFieldCalculation_CWA_TOC

{

public class CalculateParentRollupField : CodeActivity

{

 

protected override void Execute(CodeActivityContext context)

{

ITracingService tracingService = context.GetExtension<ITracingService>();

 

IWorkflowContext extension = context.GetExtension<IWorkflowContext>();

IOrganizationServiceFactory serviceFactory = context.GetExtension<IOrganizationServiceFactory>();

IOrganizationService service = serviceFactory.CreateOrganizationService(extension.InitiatingUserId);

 

Guid currentRecordId = extension.PrimaryEntityId;

string currentOperation = extension.MessageName;

string currentEntityName = extension.PrimaryEntityName;

 

string parentEntityField = ParentEntityField.Get(context).ToString().ToLower().Trim();

string parentEntityRollupField = ParentEntityRollupField.Get(context).ToString().ToLower().Trim();

 

tracingService.Trace(“Parent Entity Field On Current Entity: ” + parentEntityField + “, Field on Parent Entity To Force Recalculation: ” + ParentEntityRollupField);

 

tracingService.Trace(“Retrieving Current Entity + Parent Field”);

 

Entity currentEntity = service.Retrieve(currentEntityName, currentRecordId, new ColumnSet(parentEntityField));

 

tracingService.Trace(“Retrieved Current Entity – Retrieving Parent Entity”);

if (currentEntity.Contains(parentEntityField))

{

EntityReference parentEntityRef = (EntityReference)currentEntity[parentEntityField];

string parentEntityType = parentEntityRef.LogicalName;

string parentEntityName = parentEntityRef.Name;

tracingService.Trace(“Parent Entity Entity Type: ” + parentEntityType + “, Parent Entity Name: ” + parentEntityName);

tracingService.Trace(“Executing Calculate Rollup Request”);

 

CalculateRollupFieldRequest rollupRequest = new CalculateRollupFieldRequest { Target = parentEntityRef, FieldName = parentEntityRollupField };

 

CalculateRollupFieldResponse response = (CalculateRollupFieldResponse)service.Execute(rollupRequest);

 

tracingService.Trace(“Recalculated”);

}

 

}

[Input(“Current Entity Field Lookup To Parent”), RequiredArgument]

public InArgument<string> ParentEntityField { get; set; }

[Input(“Parent Entity Rollup Field”), RequiredArgument]

public InArgument<string> ParentEntityRollupField { get; set; }

}

}