Thursday, 17 July 2014

Different Behaviours of IOrganizationService.Create Method Triggered Synchronously and Asynchronously

When I have to create a duplicate records with common attribute values, I usually just write a Create line of code in the loop without re-initialising the object.

 Entity testRecord = new Entity("new_testentity");  
 testRecord["new_parentrecordid"] = new EntityReference("new_testparententity", parentEntityId);  
 for (int i = 0; i < itemCount; i++)  
 {  
   testRecord["new_serialno"] = i + 1;  
   service.Create(testRecord);  
 }  

Above set of code always work in console or web application that connects to CRM web service or in synchronous plug-in.
But recently, I had to change one of my plug-ins from synchronous execution mode to asynchronous resulting in the plugin failed with error message below. It occurs same if I trigger the same code as custom workflow activity.

A record with these values already exists. A duplicate record cannot be created. Select one or more unique values and try again

Exception: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Cannot insert duplicate key. (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).


Upon debugging and tracing the issue, looks like the error occurs due to creation of the same ID. But normally, when we call Create method, there is no modification to the Id property of the entity object passed as a parameter to the Create method. But in asynchronous calls, the Id property is set with the GUID of the created record. I am not sure why there is such different behaviour between calling the Create method synchronously and asynchronously. I've checked the IOrganizationService.Create Method in MSDN library but I didn't see it documented anywhere so that I am not sure it's by design or a bug. Let me know in the comment section if any of you guys have an idea about it.

Anyway, I've changed my coding style to clear the ID columns before calling Create method so that it won't cause any unnecessary error in any execution mode.

 Entity testRecord = new Entity("new_testentity");  
 testRecord["new_parentrecordid"] = new EntityReference("new_testparententity", parentEntityId);  
 for (int i = 0; i < itemCount; i++)  
 {  
   testRecord.Id = Guid.Empty;  
   if (testRecord.Contains("new_testentityid"))  
     testRecord.Attributes.Remove("new_testentityid");  
   service.Create(testRecord);  
 }  

No comments:

Post a Comment