Suite de l'article :
Numérotation automatique par workflow temps réel vs Plugin
Rappel de l'article précédent :
La numérotation automatique par workflow est facilement paramétrable mais son impact sur la création d'enregistrement est plus important qu'un plugin (120 % en plus).
Dans cet article, nous allons créer une activité de workflow personnalisée pour réduire le temps de traitement du workflow tout en gardant la flexibilité de paramétrage du workflow.
1/ Créer une entité
Counter avec les attributs :
- Name : Chaîne de caractères
- Prefix : Chaîne de caractères
- Number : Décimal
- Number Length : Décimal
- Suffix : Chaîne de caractères
2/ Créer l'activité de Workflow personnalisé.
En paramètre d'entrée, l'enregistrement Counter correspondant à la numérotation d'une entité.
En paramètre de sortie, la numérotation générée.
namespace AutoNumberingWorkflowActivity
{
using System;
using System.Activities;
using System.ServiceModel;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
public sealed class AutoNumbering : CodeActivity
{
///
/// Executes the workflow activity.
///
/// The execution context.
protected override void Execute(CodeActivityContext executionContext)
{
// Create the tracing service
ITracingService tracingService = executionContext.GetExtension();
if (tracingService == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
}
tracingService.Trace("Entered Class1.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}",
executionContext.ActivityInstanceId,
executionContext.WorkflowInstanceId);
// Create the context
IWorkflowContext context = executionContext.GetExtension();
if (context == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
}
tracingService.Trace("Class1.Execute(), Correlation Id: {0}, Initiating User: {1}",
context.CorrelationId,
context.InitiatingUserId);
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
//Create a request
RetrieveRequest _retrieveRequest = new RetrieveRequest();
_retrieveRequest.ColumnSet = new ColumnSet(new string[] { "new_prefix", "new_number","new_numberlength","new_suffix" });
_retrieveRequest.Target = Counter.Get(executionContext);
//Execute the request
RetrieveResponse _retrieveResponse = (RetrieveResponse)service.Execute(_retrieveRequest);
//Retrieve the Counter Entity
Entity _counterRecord = _retrieveResponse.Entity as Entity;
StringBuilder _sbuilder = new StringBuilder();
if (_counterRecord.Contains("new_prefix"))
{
_sbuilder.Append((String)_counterRecord["new_prefix"]);
_sbuilder.Append("-");
}
if (_counterRecord.Contains("new_numberlength"))
{
_sbuilder.AppendFormat(String.Concat("{0:D", (int)(Decimal)_counterRecord["new_numberlength"], "}"), (int)(Decimal)_counterRecord["new_number"]);
}
else
{
_sbuilder.AppendFormat("{F0}",(Decimal)_counterRecord["new_number"]);
}
if (_counterRecord.Contains("new_suffix"))
{
_sbuilder.Append("-");
_sbuilder.Append((String)_counterRecord["new_suffix"]);
}
//Set the variable
Number.Set(executionContext, _sbuilder.ToString());
//Increment
decimal _value = (Decimal)_counterRecord["new_number"];
Entity _updateCounter = new Entity("new_counter");
_updateCounter.Id = _counterRecord.Id;
_updateCounter["new_number"] = _value + 1;
service.Update(_updateCounter);
}
catch (FaultException e)
{
tracingService.Trace("Exception: {0}", e.ToString());
// Handle the exception.
throw;
}
tracingService.Trace("Exiting Class1.Execute(), Correlation Id: {0}", context.CorrelationId);
}
[RequiredArgument]
[Input("Select Counter Record")]
[ReferenceTarget("new_counter")]
public InArgument Counter { get; set; }
[Output("Number")]
public OutArgument Number { get; set; }
}
}
3/Importer cette assembly dans la solution.
4/Création du workflow.
La première étape permet de renseigner l'enregistrement pour la numérotation.
La seconde étape modifie l'attribut sur l'enregistrement cible avec le champ retourné par l'activité de workflow.
Après activation du workflow, voici les tests.
Tableau de comparaison pour un chargement de 100 enregistrements par la méthode CreateRequete.
Type de compteur | Durée en ms | Remarque |
Workflow temps réel | 7583 | Impossible de définir la longueur du nombre incrémental |
Plugin | 3450 | Trop spécifique à l'entité cible |
Activité de workflow | 5060 | Paramétrable à souhait |
L'utilisation d'une activité de workflow personnalisé permet de réduire le temps d'exécution de 30 %. De plus, le paramétrage du compteur est plus souple et permet d'ajouter une numérotation automatique sur n'importe quelle entité. Le prochain article décrira les différentes possibilités de numérotation.