Search code examples
dynamics-crmdynamics-crm-2011dynamics-crm-2013dynamics-crm-2015dynamics-crm-365

Is it possible to track changes to Entity Metadata in Dynamics CRM?


Is there any way to track changes to Metadata, like new fields, new entities and so on?

It is difficult to control a very large project in the same environment, so sometimes there are some customization that should not be deployed to productions (Mostly are mistakes or test in a development environment).

And there is a way to know who did that customization?

I am looking to know every possible change, not any in particular.


Solution

  • You have to use the RetrieveMetadataChangesRequest and it is not possible to know who made the change.

    This is available only from Microsoft Dynamics CRM 2011 Update Rollup 12

    This request is intended to be used to cache information from the metadata and be able to work offline, but we can use it to track changes to metadata in complex projects and complex teams

    Examples on internet are not very friendly so this is how you can use the request:

    The request can be completed only with filling one parameter

    RetrieveMetadataChangesRequest req = new RetrieveMetadataChangesRequest()
    {
        ClientVersionStamp = null
    };
    var response = (RetrieveMetadataChangesResponse)service.Execute(req);
    

    The first time you executed this request ClientVersionStamp needs to be null, because there was no request made to the metadata before and there is no ClientVersionStamp. This parameter is the last time you query for metadata changes and if it is null it will bring all customization from all time, so probably this request won't complete on time so we need to tune up.

    var EntityFilter = new MetadataFilterExpression(LogicalOperator.And);
    EntityFilter.Conditions.Add(new MetadataConditionExpression("SchemaName", MetadataConditionOperator.Equals, "ServiceAppointment"));
    var entityQueryExpression = new EntityQueryExpression()
            {
                Criteria = EntityFilter
            };
    RetrieveMetadataChangesRequest req = new RetrieveMetadataChangesRequest()
            {
                Query = entityQueryExpression,
                ClientVersionStamp = null
            };
    var response = (RetrieveMetadataChangesResponse)service.Execute(req);
    

    This will query all metadata changes for "ServiceAppointment", feel free to use the entity you want, but what we need is the ServerTimeStamp from the response, it will looks like "22319800!09/13/2017 16:17:46", if you try to send this time stamp first, it will throw an exception, so it is necessary to query first to get a server time stamp.

    Now you can use the request and the time stamp to retrieve all new changes since "22319800!09/13/2017 16:17:46"

    RetrieveMetadataChangesRequest req = new RetrieveMetadataChangesRequest()
            {
              Query = entityQueryExpression,
              ClientVersionStamp = @"22319800!09/13/2017 16:17:46"
            };
    
    var response = (RetrieveMetadataChangesResponse)service.Execute(req);
    

    You can filter the query to match your needs, only search for specific entities, labels, relationship, keys and attributes or specific properties.

    EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
    {
        Criteria = EntityFilter,
        Properties = EntityProperties,
        RelationshipQuery = new RelationshipQueryExpression()
        {
            Properties = RelationshipProperties,
            Criteria = RelationshipFilter
        },
        AttributeQuery = new AttributeQueryExpression()
        {
            Properties = AttributeProperties,
            Criteria = AttributeFilter
        }
    };
    

    Use this request and implement it the way you need.