0

I've created and deployed a plugin for the Update event of a custom entity but it seems when multiple users update different entities within quick succession the plugin uses the first entity it receives for each call.

To investigate further I added NLog via NuGet and at the beginning of the Execute function I generate a Guid and log the entity Id and the Guid. When I look in the log I can see the same ID and Guid logged 3-4 times before both change.

What I think is happening is the code is being run for each user but using the first entities details, applying only to the first entity.

Why is this happening and how can I stop it? The problem is users are saying the plugin is erratic.

Here is my code:

    public class OnUpdateClaimSection : IPlugin
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private string logId = Guid.NewGuid().ToString();

        public void Execute(IServiceProvider serviceProvider)
        {
            try
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    logger.Debug("{0} {1}|{2}|{3}", logId, context.MessageName, context.PrimaryEntityName, Common.GetSystemUserFullName(service, context.UserId));

                    var entity = context.InputParameters["Target"] as Entity;
                    logger.Debug("{0} {1}", logId, entity.Id);
                    var claimSection = GetClaimSection(service, entity.ToEntity<ClaimSection>());                  

                    CalculateClaimTotals(service, claimSection);
                }
            }
            catch (Exception ex)
            {
                logger.Error("{0} Exception : {1}", logId, ex.Message);
                throw;
            }
        }
    }
Andre Odendaal
  • 557
  • 6
  • 19

1 Answers1

0

Plugin classes are instantiated once by the CRM platform and are then reused for requests. Therefore you must be very careful when using class field variables, because they are not guaranteed to be thread-safe.

In your example field logId is modified in the Execute method. Race conditions of multiple threads are causing the effects you describe.

I suggest to only use plugin class fields when you have made sure that their implementation is absolutely thread-safe.

Henk van Boeijen
  • 7,357
  • 6
  • 32
  • 42