'Dynamics 365 RetrieveEntityChangesRequest not returning all expected attributes

We are migrating from CRM on prem to dynamics 365 and need to change the mechanism used to populate our data warehouse with change data. Previously we used SQL Server change data capture, which was extremely simple, but of course we don't have database access in 365. >:(

So, I am attempting to send a RetrieveEntityChangesRequest via a CrmServiceClient instead. The request appears to work successfully, and I do get a response, but if I iterate over the attributes in the returned entities, they do not contain all of the fields I specified in the request. If I use the Query.ColumnSet(true) overload (to return all columns), I only get about a third of the fields that I can see in the web UI (that is to say, in settings > customizations > customize the system > entities > account > fields).

If I try to pull one of the "missing" fields explicitly, for example using Query.ColumnSet("accountnumber") then I get a response, not an exception, but the response does not include the field. On the other hand, if I use Query.ColumnSet("notarealcolumn") I get an exception. So the system recognises that the accountnumber field is a valid field, but it's not being returned.

I considered the possibility that perhaps the RetrieveEntityChangesRequest only returns fields where a value has in fact changed, but this can't be the explanation since I am not populating the request's DataVersion property in my test code, which I believe should mean "everything" is returned (not just changes) because it represents the initial state, not a delta per se.

What am I missing?

What follows is a sample console application which demonstrates this behaviour. It was built with a reference to the Microsoft.CrmSdk.XrmTooling.CoreAssembly nuget package, version 9.1.0.110.

CrmServiceClient client = new CrmServiceClient
(
   new Uri(@"https://myorghere.crm6.dynamics.com"),
   @"redacted",
   @"redacted",
   false,
   @"..\"
);

RetrieveEntityChangesRequest req = new RetrieveEntityChangesRequest();
req.EntityName = "account";
req.Columns = new Microsoft.Xrm.Sdk.Query.ColumnSet(true); // get all columns!     
req.PageInfo = new Microsoft.Xrm.Sdk.Query.PagingInfo() {  Count = 1, PageNumber = 1};
var resp = (RetrieveEntityChangesResponse)client.Execute(req);
foreach (var item in resp.EntityChanges.Changes)
{
   if (item.Type == ChangeType.NewOrUpdated)
   {
      var e = (item as NewOrUpdatedItem).NewOrUpdatedEntity;
      // our account entity has an "accountnumber" attribute, but it is not returned (and many other attributes are not returned either)
         foreach (var item in resp.EntityChanges.Changes)
         {
            if (item.Type == ChangeType.NewOrUpdated)
            {
               var e = (item as NewOrUpdatedItem).NewOrUpdatedEntity;
               foreach (var a in e.Attributes.OrderBy(a => a.Key))
               {
                  var val = a.Value is OptionSetValue v ? e.FormattedValues[a.Key]
                              : a.Value is Money m ? m.Value
                              : a.Value is EntityReference r ? r.Id
                              : a.Value;

                  Console.WriteLine($"{a.Key} = {val ?? "null"} ");
               }
               
            }                 
         }     
   }                 
}
Console.ReadKey();


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source