Saturday, June 05, 2010

MSCRM 4.0: A Few Tips on Using CRM Configuration Data Utility

In case you are not aware, CRM Configuration Data Utility is a handy tool released by Microsoft sometime last year. What it does is to help you transfer CRM configuration data from one environment to another.

I recently happen to have the need to transfer some configuration data between two environments, so I spent a little time to poke around with the utility, and I am very pleased with the tool, but I quickly realized a few limitations with the toolkit that have been intentionally engineered by Microsoft team. Fortunately the utility comes with complete source code, so I was able to tweak it to meet my needs. Here are a couple of tips that might help you make best use of the tool.

  1. This utility is a really convenient tool if you want to transfer any configuration data stored in your custom entities. You can export data from one environment, and import to another one within a few mouse click. But here is the catch, it's engineered to only support the export and import of custom entities. But with the source code, you can easily change it to support any entities including system ones. What you need to do is to change the following code in ExportDataForm.cs file (RetrieveEntitiesComplete method)
    IEnumerable<EntityMetadata> entities = response.CrmMetadata
        .Cast<EntityMetadata>()
        .Where(entity => entity.IsIntersect.Value == false && entity.IsImportable.Value && entity.IsCustomEntity.Value)
        .OrderBy(entity => entity.DisplayName.UserLocLabel.Label)
        .ToList();
    
    
    to
    IEnumerable<EntityMetadata> entities = response.CrmMetadata
        .Cast<EntityMetadata>()
        .Where(entity => entity.IsIntersect.Value == false && entity.IsImportable.Value)
        .OrderBy(entity => entity.DisplayName.UserLocLabel.Label)
        .ToList();
    
    

  2. The utility is a smart tool, but it is a little bit too smart when it comes to the import. It will actually try to do duplicate check before importing the data. The duplicate check is based on the imported entity's primary attribute, which isn't correct all the time. Sometimes, we do have two different CRM records with the same value of the primary attribute. For instance, we have a self-referenced entity, which has a parent field to refer to the same entity itself. It's often the case that the primary attribute of two CRM records are the same, but they are linked to two different parents, they are essentially two different records in the business world. In order to have the utility to do straight import, you should comment out the following code in dynamicentityutility.cs file (GetByIdOrPrimaryAttribute method)
    // Locate the following code and comment out the entire block in dynamicentityutility.cs file
    // in order to stop the configuration data utility from performing duplicate check. 
    string primaryAttribute = MetadataUtility.RetrievePrimaryAttribute(metadataService, entityName);
    QueryExpression query = new QueryExpression(entityName)
    {
        ColumnSet = new ColumnSet(fields)
    };
    
    ConditionExpression primaryAttributeExpression = new ConditionExpression(primaryAttribute.ToLower(), ConditionOperator.Equal, primaryAttributeValue);
    query.Criteria.Conditions.Add(primaryAttributeExpression);
    
    RetrieveMultipleRequest request = new RetrieveMultipleRequest()
    {
        Query = query,
        ReturnDynamicEntities = true
    };
    
    RetrieveMultipleResponse response = (RetrieveMultipleResponse)_crmService.Execute(request);
    
    if (response.BusinessEntityCollection.BusinessEntities.Count > 0)
        resultList.AddRange(response.BusinessEntityCollection.BusinessEntities.ConvertAll<DynamicEntity>(x=> (DynamicEntity)x));
    

The beauty about this tool is, you often configure your CRM workflows in one environment (for instance, your development environment), and those CRM workflows sometimes refer to particular CRM records as configuration data, so there is dependency between your workflow and those CRM records. When you export those workflows and import to a different environment (for instance, your production environment), you will have to re-create the same set of CRM records in the new environment in order to make the workflows work. But if you create the records manually, the records' internal ID (Guid) would be different, so you will have to reconfigure each workflow to point to the new created CRM records, otherwise, you would not be able to publish your workflows. But with the configuration data utility handy, you can simply transfer the configuration data, the IDs will remains the same as what it was in the original environment, so you don't have to reconfigure your workflows, it will save you tremendous effort when you try to promote workflows from one environment to another which have dependency on configuration data.

Hope this gives you some basic ideas about how to tweak the utility. In my opinion, it's a pretty well-engineered piece of software.