Search code examples
dynamics-crmdynamics-crm-2011dynamics-crm-2013dynamics-crm-onlinepowerapps-modeldriven

Dynamics crm + Plugin code to store sum formula across a entity collection


I have the below requirement to be implemented in a plugin code on an Entity say 'Entity A'-

Below is the data in 'Entity A'

Record 1 with field values

  • Price = 100
  • Quantity = 4

Record 2 with field values

  • Price = 200
  • Quantity = 2

I need to do 2 things

  1. Add the values of the fields and update it in a new record
  2. Store the Addition Formula in a different config entity

Example shown below -

Record 3

  • Price
    Price Value = 300 Formula Value = 100 + 200

  • Quantity Quantity Value = 6 Formula Value = 4 + 2

Entity A has a button named "Perform Addition" and once clicked this will trigger the plugin code.

Below is the code that i have tried -

AttributeList is the list of fields i need to perform sum on. All fields are decimal

Entity EntityA = new EntityA();
EntityA.Id = new Guid({"Guid String"});

var sourceEntityDataList = service.RetrieveMultiple(new FetchExpression(fetchXml)).Entities;

foreach (var value in AttributeList)
{
   EntityA[value]= sourceEntityDataList.Sum(e => e.Contains(value) ? e.GetAttributeValue<Decimal>(value) : 0);
}

service.Update(EntityA);

I would like to know if there is a way through linq I can store the formula without looping? and if not how can I achieve this?

Any help would be appreciated.


Solution

  • Here are some thoughts:

    It's interesting that you're calculating values from multiple records and populating the result onto a sibling record rather than a parent record. This is different than a typical "rollup" calculation.

    Dynamics uses the SQL sequential GUID generator to generate its ids. If you're generating GUIDs outside of Dynamics, you might want to look into leveraging the same logic.

    Here's an example of how you might refactor your code with LINQ:

    var target = new Entity("entitya", new Guid("guid"));
    
    var entities = service.RetrieveMultiple(new FetchExpression(fetchXml)).Entities.ToList();
    
    attributes.ForEach(a => target[a] = entities.Sum(e => e.GetAttributeValue<Decimal>(a));
    
    service.Update(target);
    

    The GetAttributeValue<Decimal>() method defaults to 0, so we can skip the Contains call.

    As far as storing the formula on a config entities goes, if you're looking for the capability to store and use any formula, you'll need a full expression parser, along the lines of this calculator example. Whether you'll be able to do the Reflection required in a sandboxed plugin is another question.

    If, however, you have a few set formulas, you can code them all into the plugin and determine which to use at runtime based on the entities' properties and/or config data.