When I first started playing around with CRM 2011 plug-ins, I pretty much dove in headfirst to see what I could do. Sure, I browsed the SDK and modeled my code after the examples, but I ended up running into a nasty issue with one of my embellishments. What I thought was an innocuous method of handling the IOrganizationService proved to be problematic, considering how CRM 2011 plug-ins function.
I was creating the service like you usually do:
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>(); IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>(); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
Then I made a horrible mistake:
CrmData.Service = service;
At the time, I thought: “It sure is nice and clean, keeping all my data access methods in a separate class! Why don’t I just plop the service into some variable so I don’t have to pass it for each method call?” Little did I know that my choice to not RTFM would’ve told me exactly why I shouldn’t do that.
From MSDN’s Write a Plug-In article:
For improved performance, Microsoft Dynamics CRM caches plug-in instances. The plug-in’s Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. Also, multiple system threads could execute the plug-in at the same time. All per invocation state information is stored in the context, so you should not use global variables in plug-ins or attempt to store any data in member variables for use during the next plug-in invocation.
The worst part about this is that it works great, up until you have the plug-in firing more than once, simultaneously. Various errors will be logged, from messages about the service already being in use to errors exclaiming that basic interal CRM functionality, such as RetrieveMultiple, cannot be found.
So, for anyone else out there who has a CRM 2011 plug-in that’s failing in strange and inconsistent ways, you may want to see if you’re keeping your IOrganizationService on a short leash. Sending it away to another class to be used indiscriminately by any ol’ plug-in execution is a surefire way to pad the server error logs!