Buenas, como muchos ya conocen y (espero) estén utilizando ya, en Dynamics CRM 2015 tenemos la posibilidad de utilizar campos de tipo “Consolidados” o de tipo “Rollup” (a veces las traducciones no me suenan muy bien y prefiero hablar con conceptos en inglés).
Bien, este tipo de campos tiene la particularidad que se calculan de forma asíncrona, es decir que es posible que el dato que estemos consultando o viendo, no sea esté actualizado. Esto se puede minimizar, bajando los tiempos de cálculo hasta un mínimo de una hora, pero aún así, en algunos escenarios esto no alcanza y es requerido que los cálculos sean totalmente online.
Hoy les voy a enseñar como convertir un campo de tipo Rollup (asíncrono por naturaleza), a un campo de Rollup 100% síncrono.
Me he inventado un escenario donde tengo Cuentas y Contactos (muy original por cierto) y quiero un campo en las Cuentas que me muestre el total de Contactos relacionados que dispone.
El campo de Rollup en Cuenta tiene la siguiente definición:

Bien, solamente con esto ya dispongo del campo que me calcula el total de contactos relacionados con una Cuenta. Pero esto se calcula de forma asíncrona nomás, o síncrona de forma manual desde el mismo formulario.
Para convertirlo en totalmente síncrono, debemos crear un Plugin y hacer una llamada a un nuevo mensaje llamado “CalculateRollupFieldRequest” que permite disparar el cálculo de un campo de tipo Rollup.
El código completo del Plugin está aquí:
using Microsoft.Crm.Sdk.Messages;using Microsoft.Xrm.Sdk;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Web;
namespace Plugin_Recalculate_Rollup
{
public class Recalculate_Rollup :IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =(ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName != "contact")
return;
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
Entity contact=(Entity)context.PostEntityImages["Imagen"];
CalculateRollupFieldRequest calculateRollup = new CalculateRollupFieldRequest();
calculateRollup.FieldName = "new_totaldecontactos";
calculateRollup.Target = new EntityReference("account", ((EntityReference)contact.Attributes["parentcustomerid"]).Id);
CalculateRollupFieldResponse resp = (CalculateRollupFieldResponse)service.Execute(calculateRollup);
}
catch (Exception ex)
{
tracingService.Trace("MyPlugin: {0}", ex.ToString());
throw;
}
}
}
}
}
En la llamada al “CalculateRollupFieldRequest”, solamente hay que pasarle los siguientes parámetros:
- FieldName: con el nombre del campo Rollup en Cuenta
- Target: que debe ser un EntityReference al registro “padre”
Este plugin, lo complilamos y lo registramos con el PluginRegistrationTool como siempre.
NOTA: para registrar plugins a mí el PluginRegistrationTool de la versión 7.0.0 (CRM 2015) no me funciona, ya que se me queda la pantalla en blanco al conectar. Para este ejemplo he utilizado el PluginRegistrationTool que viene en la SDK de CRM 2013 SP1 (6.1.0).
Adicionalmente he credo una Imagen Post para recoger el “ParenCustomerId” del contacto:
Ahora cada vez que crea un Contacto nuevo relacionado con una Cuenta, se recalcula el campo de tipo Rollup:
Advertencia!: los campos de tipo Rollup síncronos pueden penalizar (y mucho) el rendimiento del CRM, por esto, si bien una práctica 100% soportada, utilizarlos con cuidado.