The Problem
I was trying to export a Solution from Dynamics 365 CE / Dynamics CRM to deploy into the next environment, but instead I got a Query Builder Error: The specified field does not exist in Microsoft Dynamics 365.
Looking into the log file I saw the following message:
The attribute with AttributeId = ‘21549767-ae60-4fa6-9d88-a21146141b5f’ was not found in the MetadataCache
The root cause of the Query Builder Error
The root cause of this problem is that I removed a field from Dynamics 365 CE / CRM, but the solution still has a reference to the deleted field. The solution has an orphan Solution Component pointing to nothing. This blocks the exporting of the solution.
By using the following FetchXML query the Solution Component can be found:
<fetch top="10">
<entity name="solutioncomponent">
<all-attributes/>
<filter type="and">
<condition attribute="objectid" operator="eq" value="<AttributeId>" />
</filter>
</entity>
</fetch>
Probably a good guideline would be that whenever your remove something from the Dynamics 365 CE / CRM system, that you first remove it from the solution and then delete it from the system.
Fixing it
Fix by using RemoveSolutionComponentRequest
The first thing I tried was to remove the orphan Solution Component by executing a RemoveSolutionComponentRequest
. I created the following Console App to do this.
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System;
namespace FixAttributeNotFoundMetadataCache
{
internal class Program
{
private static void Main(string[] args)
{
var solutionName = "<Your Solution Name>";
var attributeId = new Guid("<AttributeId found in the errorlog>");
var client = new CrmServiceClient("<Your Connectionstring>");
if (!client.IsReady)
throw new Exception(client.LastCrmError, client.LastCrmException);
// Find related Solution Component
var query = new QueryExpression("solutioncomponent")
{
ColumnSet = new ColumnSet(true),
Criteria = new FilterExpression(LogicalOperator.And)
{
Conditions =
{
new ConditionExpression("objectid", ConditionOperator.Equal, attributeId)
}
}
};
var solutionComponents = client.RetrieveMultiple(query).Entities;
// Delete Solution Components
foreach(var component in solutionComponents)
{
var componentId = component.GetAttributeValue<Guid>("solutioncomponentid");
var componentType = component.GetAttributeValue<OptionSetValue>("componenttype").Value;
var removeComponentReq = new RemoveSolutionComponentRequest()
{
ComponentId = componentId,
ComponentType = componentType,
SolutionUniqueName = solutionName
};
var response = client.Execute(removeComponentReq);
}
}
}
}
Unfortunately, when I executed the request it complained that the Solution Component couldn’t be found in the specified solution. I couldn’t resolve this bug, so I went with the next approach.
[UPDATE] To solve the bug I should have used objectid instead of solutioncomponentid for the ComponentId in the request.
Fix by removing the Entity from the solution
My next thinking was to remove the Entity, from which I deleted the field, completely from the solution then re-add it back to the solution. Hopefully by doing so the orphan Solution Component would also be removed.
By doing this trick the Query Builder Error problem was finally resolved :-D.