Updating an entity's related entity set
The problem:
I had an issue with entity updates from a CRM solution. I have a plug-in with a step registered on the Update event, fired by a jscript call to Save(). This allows me to trigger the plug-in manually with my own button. The feature requirement is to update not the current record, but its related entity records. The plug-in was retrieving the set of related entities for the record without any issues using the below code, but got an error when I tried to update – update code is highlighted:
Entity var = service.Retrieve(logicalName, id, new ColumnSet(true));
QueryExpression query = new QueryExpression();
query.EntityName = "new_casequery";
query.ColumnSet = new ColumnSet(true);
Relationship relationship = new Relationship();
relationship.SchemaName = " rollupitem_ individualitem ";
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(relationship, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet("recname");
request.Target = new EntityReference { Id = id, LogicalName = logicalName};
RetrieveResponse response = (RetrieveResponse)service.Execute(request);
if (((DataCollection<Relationship, EntityCollection>)(((RelatedEntityCollection)(response.Entity.RelatedEntities)))).Contains(new Relationship("rollupitem_ individualitem "))
&& ((DataCollection<Relationship, EntityCollection>)(((RelatedEntityCollection)(response.Entity.RelatedEntities))))[new Relationship("rollupitem_ individualitem ")].Entities.Count > 0)
{
EntityCollection relatedset = response.Entity.RelatedEntities[new Relationship("rollupitem_ individualitem ")];
foreach (Entity ent in relatedset.Entities)
{
service.Update(ent);
string s =context.OrganizationName;
}
}
With this code the OganizationService.Update(Entity) method threw a SystemException (with the really useful error message "An unexpected error occurred.") The inner exception was a base ServiceModel.FaultException with the same message ("An unexpected error occurred").
The trace log also proved to be of little help, although it reaffirmed that the issue was with the update:
Crm Exception: Message: An unexpected error occurred., ErrorCode: -2147220970
[2012-6-14 00:50:26.393] Process: w3wp |Organization:6e40b889-63d2-e011-9e55-00155d883f98 |Thread: 52 |Category: Application |User: 00000000-0000-0000-0000-000000000000 |Level: Error | ErrorInformation.LogError
at ErrorInformation.LogError()
at ErrorInformation..ctor(Exception exception, Uri requestUrl, Boolean logError)
at ErrorInformation..ctor(Exception exception, Uri requestUrl)
at AppForm.HandleSaveEntityException(Exception exception, FormEventId eventType, String url)
at AppForm.SaveEntity(EntityProxy entity, FormEventId eventType, String redirectPath, Boolean performDuplicateCheck)
at AppForm.Save(Boolean& gridRefreshCallbackAdded)
at AppForm.FormSaveEvent()
at AppForm.RaiseDataEvent(FormEventId eventId)
at EndUserForm.Initialize(Entity entity)
at CustomizableForm.Execute(Entity entity, FormDescriptor fd)
at CustomizableForm.Execute(Entity entity, FormType formType)
at CustomizableForm.Execute(Entity entity)
at UserDefinedRecordPageHandler.ConfigureFormHandler()
at GenericEventProcessor.RaiseEvent(String eventName)
at PageManager.OnPreRender(EventArgs e)
at Control.PreRenderRecursiveInternal()
at Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at Page.ProcessRequest()
at Page.ProcessRequest(HttpContext context)
at intlorg_userdefined_edit_aspx.ProcessRequest(HttpContext context) c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\8dfc503f\901eed87\App_Web_r1i1ko2i.0.cs
at CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at ApplicationStepManager.ResumeSteps(Exception error)
at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType)
>MSCRM Error Report:
--------------------------------------------------------------------------------------------------------
Error: An unexpected error occurred.
Error Number: 0x80040216
Error Message: An unexpected error occurred.
Error Details: An unexpected error occurred.
Source File: Not available
Line Number: Not available
Request URL: https://localhost/IntlOrg/userdefined/edit.aspx?_gridType=10004&etc=10004&id=%7b789168F6-10F0-E011-8589-AA0000D70005%7d&pagemode=iframe&rskey=761556402&sitemappath=Workplace%7cMyWork%7cnav_dashboards
Stack Trace Info: [CrmException: An unexpected error occurred.]
at Microsoft.Crm.Application.Platform.ServiceCommands.PlatformCommand.XrmExecuteInternal()
at Microsoft.Crm.Application.Platform.ServiceCommands.UpdateCommand.Execute()
at Microsoft.Crm.Application.Platform.DataSource.Update(EntityProxy entity, Boolean performDuplicateCheck, Guid auditingTransactionId, IOrganizationContext context)
at Microsoft.Crm.Application.Platform.EntityProxy.Update(Boolean performDuplicateCheck, Guid auditingTransactionId)
at Microsoft.Crm.Application.Platform.EntityProxy.Update(Boolean performDuplicateCheck)
at Microsoft.Crm.Application.Forms.AppForm.SaveEntity(EntityProxy entity, FormEventId eventType, String redirectPath, Boolean performDuplicateCheck)
The fix:
There may be another way to do this but in the end this is what worked for me. It seems the entities in the related set collection are just not available for update and are just for reference . Once I instantiated each one as individual entity objects as in the following snippet, the update worked fine:
foreach (Entity ent in relatedset.Entities)
{
Entity updateable = service.Retrieve(ent.LogicalName, ent.Id, new ColumnSet("new_btnfield"));
updateable.Attributes["new_btnfield"] = "1";
service.Update(updateable);
}