none
Dynamics CRM 2011 Plugin Transaction Disallows IOrganizationService.Create for Related Entities

    Question

  • Hi,

    I have a synchronous post-operation (40) plugin on SystemUser for MessageName = Create that obviously runs in a transaction. within the Execute method of the plugin, I try to use the IOrganizationService.Create method to add a related entity. This obviously fails as the database transaction hasn't been committed yet. Is there a way that I can commit the database transaction in order to add the related entity? Alternatively, is there a way to kick off another process to add the related entity and allow the plugin to complete, committing the transaction? I have tried using Thread and BackgroundWorker to no avail. Here is the code:

      /// <summary>
      /// User Plugin Class.
      /// </summary>
      public class UserPlugin : IPlugin
      {
        IPluginExecutionContext context;
        Entity entity;
        IOrganizationServiceFactory serviceFactory;
        IOrganizationService service;
        bool isPostSave;
        SystemUser systemUser;
    
        /// <summary>
        /// Execute Method of Plugin.
        /// </summary>
        /// <param name="serviceProvider">Service Provider.</param>
        public void Execute(IServiceProvider serviceProvider)
        {
          try
          {
            new PluginParameterExporter().ExportServiceProviderTestParametersToXml(serviceProvider);
          }
          catch (FaultException<OrganizationServiceFault> ex)
          {
            Debug.WriteLine("Unable to export service provider test parameters to XML. The exception was: " + ex.Message);
          }
          if (serviceProvider != null)
          {
            context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
              entity = (Entity)context.InputParameters["Target"];
              if (entity.LogicalName != SystemUser.EntityLogicalName)
              {
                return;
              }
            }
            else
            {
              return;
            }
            try
            {
              serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
              service = serviceFactory.CreateOrganizationService(context.UserId);
              isPostSave = context.Stage == 40 || context.Stage == 50 ? true : false;
              if (context.Depth < 2 && context.MessageName == "Create" && isPostSave)
              {
                systemUser = entity.ToEntity<SystemUser>();
                if (systemUser.SystemUserId.HasValue)
                {
                  systemUser = service.Retrieve(SystemUser.EntityLogicalName, systemUser.SystemUserId.Value, new ColumnSet(true)).ToEntity<SystemUser>();
                }
                if (!context.IsInTransaction)
                {
                  new Employee().ProcessNewEmployee(service, systemUser);
                }
                else
                {
                  //TODO: Get this to execute in a separate process.
                  //new Employee().ProcessNewEmployee(service, systemUser);
                }
              }
            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
              throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
            }
          }
        }
      }

    new Employee().ProcessNewEmployee calls the service.Create method to create a related entity record.

    Any suggestions would be greatly appreciated.

    Kind Regards,

    Johan Küstner

    Wednesday, July 13, 2011 5:24 PM