The ‘additive’ nature of CRM deployments means that it can be easier to add components to an instance of CRM than it is to remove them.
With the additive model, even if you delete a component from your development environment and then export and deploy the solution which contained that component elsewhere, the deleted component will still exist in the target environment. As a result of this, there is a danger that CRM deployments can become littered with redundant components as the cost of the housekeeping required to remove these components from production environments can be seen as quite high.
As part of our Continuous Integration process, we have started to remove redundant artifacts from CRM. For example, attributes, entities and workflows which are no longer needed are removed to keep the solutions as clean as possible. Scripting the housekeeping tasks is actually quite straightforward, and once you have done this a couple of times you will see that it is easy to create a set of standard scripts to remove redundant components.
Removing entities and their relationships can all be scripted using standard calls to the metadata API such as DeleteRelationshipRequest and DeleteEntityRequest. However, these components cannot be deleted if they exist on a form. Therefore if you want to be able to automate the deletion process, you will need to script the removal of the items from the forms on which they appear.
Imagine the scenario where you have two entities in a one-to-many relationship, neither of which is required any more. Entity A is the ‘parent’ of entity B. The Entity A form contains a section with an associated view of Entity B and the Entity B form displays a lookup to Entity B.
To remove the entities manually, the process would be:
Fortunately, scripting the removal of fields or sections from a form can be done quite easily. We can write a query which retrieves the form xml, identify the xml node which needs removing, update the form xml and publish the new version of the form.
The script will have three stages:
1 – Retrieve the Form XML for the entity in question
2 – Remove references to the entity from the form XML
For each form record returned in the above query, we can cast the formXML attribute as XML, and search for the particular node which references the item we want to remove. Once we have found the relevant node, we can then remove it from the formXml, and update the formXml on the entity and update it.
We will use an XPath expression to search the XML for a particular node. The XPath expression will depend on whether we are looking for an entity (a lookup field) or a section (containing an associated view).
If the XPath expression returns a result, we can then remove the node and update the form:
3 – Publish the changes
Your changes to the form will not be permanent unless you publish them (which means you can practice the process in Dev until you are sure it is right).
You can publish changes to an entity using a method like this:
We will need to do the same if there are any views of Entity A which contain any attributes from Entity B – we will not be able to delete the relationship between the entities whilst these attributes are on the view. As before, we can query the fetchXml and the layoutXML of the view and update it. For example, we can use a fetchXml query like the one below to find any views based on a particular entity:
and we can then modify the “layoutxml” and “fetchxml” attributes of the returned query definitions to remove any reference to the attributs which we want to remove.
With this technique it is easy to automate the process of removing sections or attributes from forms, or attributes from views, which will then enable you to programatically remove relationships between entities and the entities themselves.