Dynamics Crm Bulk Update records in a transaction

Viewed 52

Requirement

  1. I have the requirement where I want to update few fields on account and create contact for it reading data from an API.
  2. The number of records to be updated is around 100,000 so I want to
    use either ExecuteTransactionRequest or ExecuteMultipleRequest so that I can execute all in batches.

Since I want the contact record to be created for the account updated I used the ExecuteTransactionRequest.

Problem -

The problem is batch size. I have added the condition if request batch size count equals 500 then execute all the requests. However my batch can include

  • Update request for account and
  • Create request for contact

So it may happen that the batch may not be exact 500 and it would skip the execute request. How can I do this and make sure that contact record is created for each Updated Account correctly.

Any help would be appreciated. Thanks in Advance

Below is my code --

  var requests = new ExecuteTransactionRequest
        {
            Requests = new OrganizationRequestCollection(),
            ReturnResponses = returnResponses
        };

  foreach (var customer in customerList)
        {
            string custNo = customer.GetAttributeValue<string>("customernumber");

            // Gets customer details from another api
            var custInfo = await CustomerService.Get(custNo);

            // Update the values on customer table
             Entity cust = new Entity("account");
             cust.Id = customer.Id;
             cust["companytypecode"] = custInfo.EntityTypeCode;
             cust["companytypedescription"] = custInfo .EntityTypeDescription;
             

            var roles = custInfo.Roles.Where(c => c.RoleStatus == "ACTIVE").ToArray();
           //create contact for each account
           foreach(var role in roles)
           {
            Entity contact = new Entity("contact");
            contact["FirstName"] = role.RolePerson?.FirstName;
            contact["MiddleName"] = role.RolePerson?.MiddleNames;
            contact["LastName"] = role.RolePerson?.LastName;
            contact["AccountId"] = new EntityReference("account", customer.Id);

            CreateRequest createRequest = new CreateRequest { Target = contact };
            requests.Requests.Add(createRequest);
          }
           
            UpdateRequest updateRequest = new UpdateRequest { Target = cust };
            requests.Requests.Add(updateRequest);

            if (requests.Requests.Count == 500) // Problem is the batch size will not execute per account since it also has create request of contact. How can i make sure that each request is executed correctly
            {
                service.Execute(requests);
                requests.Requests.Clear();
            }
        }
      // For the last remaining accounts
        if (requests.Requests.Count > 0)
        {
            service.Execute(requests);

        }
1 Answers

Thank you for helping out. I resolved this with below solution. Happy to be corrected.

        EntityCollection requestsCollection = new EntityCollection();
        foreach (var customer in customerList)
        {
            string custNo= customer.GetAttributeValue<string>("customernumber");

            
            var custInfo = await businessService.Get(custNo);

            
         Entity cust = new Entity("account");
         cust.Id = customer.Id;
         cust["companytypecode"] = custInfo.EntityTypeCode;
         cust["companytypedescription"] = custInfo .EntityTypeDescription;
         requestsCollection.Entities.Add(cust);
            
       
        var roles = custInfo.Roles.Where(c => c.RoleStatus == "ACTIVE").ToArray();
       
       foreach(var role in roles)
       {
        Entity contact = new Entity("contact");
        contact["FirstName"] = role.RolePerson?.FirstName;
        contact["MiddleName"] = role.RolePerson?.MiddleNames;
        contact["LastName"] = role.RolePerson?.LastName;
        contact["AccountId"] = new EntityReference("account", customer.Id);

        requests.Entities.Add(contact);
      }

            
            if (requestsCollection.Entities.Count > 500)
            {
                
                ExecuteBulkUpdate(requestsCollection);
                requestsCollection = new EntityCollection();
                
            }
        }
private void ExecuteBulkUpdate(EntityCollection requestsCollection)
    {
        var requests = new ExecuteTransactionRequest
    {
        Requests = new OrganizationRequestCollection(),
        ReturnResponses = returnResponses
    };
        foreach (var request in requestsCollection.Entities)
        {
            if (request.Id != Guid.Empty)
            {   
                UpdateRequest updateRequest = new UpdateRequest { Target = request };
                requests.Requests.Add(updateRequest);
            }
            else
            {
                CreateRequest createRequest = new CreateRequest { Target = request };
                requests.Requests.Add(createRequest);
            }
        }

        try
        {
            var responseForCreateRecords = (ExecuteTransactionResponse)service.Execute(requests);
            
            int i = 0;
            // Display the results returned in the responses.
            foreach (var responseItem in responseForCreateRecords.Responses)
            {
                if (responseItem != null)
                    log.LogInformation(responseItem.Results["id"].ToString());
                i++;
            }
            requests.Requests.Clear();
        }
        catch (FaultException<OrganizationServiceFault> ex)
        {
            log.LogInformation("Request failed for the {0} and the reason being: {1}",
                ((ExecuteTransactionFault)(ex.Detail)).FaultedRequestIndex + 1, ex.Detail.Message);
            throw;
        }
    }
Related