You can lookup the error code (-2147220891) in the CRM SDK. In the help-file search for Web Service Error Codes. The codes are in hexadecimal format. Yours is 0x80040265, "ISV code aborted the operation.".
Your code snippet does not contain the complete class, but I noticed the Execute method references some variables that do not have a local scope:
Apparently these variables are fields belonging to the plugin class.
Dynamics CRM instantiates plugin classes once and reuses the instances on multiple threads. Using fields on plugin classes is therefore NOT threadsafe.
You will have to remove these fields first.
Your plugin shows multiple other issues:
- Your code does work that may prove to be unnecessary. E.g. when your plugin is handling the Create or Update message, you do not need to check the existence and type of the Target parameter.
- Getting values from the entity's Attributes collection should preferrably not be done through the item selector, because attributes having a
NULL
value in the database will not be added to the collection when retrieved from the OrganizationService. Use method GetAttributeValue<T>
instead.
- The value in dc_AppId will not contain an Id (
Guid
), but the display name of the record (string
). Also, should its value not be passed into the FetchXML?
- In your code you are using the
targetEntity.Id
property. For the Create message this property will return a Guid.Empty
in the PreValidation and PreOperation stages. In the PostOperation and AsyncOperation stages the Id can be retrieved from the OutputParameters
collection. (The key is 'id'.)
- You are using FetchXML to query data. In CRM 2011 it is better to use a
QueryExpression
(or a Linq-query) instead. In plugins you only need FetchXml for aggregate queries (count, sum, average).
- Note that tracing can only be retrieved from the plugin when an Exception has been thrown.
I restructured your plugin a bit in the snippet below:
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.MessageName != "Create" && context.MessageName != "Update")
return;
var targetEntity = (Entity)context.InputParameters["Target"];
if (targetEntity.LogicalName != "new_designconsultation")
return;
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
var dc = service.Retrieve("new_designconsultation", targetEntity.Id,
new ColumnSet("new_applicationtodesignconsultationid", "unit1apartment"));
var dc_AppId = dc.GetAttributeValue<EntityReference>("new_applicationtodesignconsultationid");
if (dc_AppId == null)
return;
// TODO: pass dc_AppId.Id into your Fetch XML.
var fetchURAs = @"
<fetch distinct='true' mapping='logical'>
<entity name='new_ura'>
<attribute name='new_uraid'/>
<attribute name='new_name'/>
<attribute name='new_app_uraid'/>
<attribute name='suiteapt'/>
<filter type='and'>
<condition attribute='suiteapt' operator='not-null'/>
</filter>
</entity>
</fetch>";
EntityCollection _URAs = service.RetrieveMultiple(new FetchExpression(fetchURAs));
// TODO: continue processing here...
}
catch (FaultException<OrganizationServiceFault> ex)
{
tracingService.Trace(ex.ToString());
throw new InvalidPluginExecutionException("An error occurred in Update plug-in.", ex);
}
catch (Exception ex)
{
tracingService.Trace("Update: {0}", ex.ToString());
throw;
}
}
You can make debugging easier when you attach VS to the W3WP process or to the CRM Asynchronous Service (for asynchronous plugins).