I'm in big trouble. The execution time of my multiple requests in the code is being longer than the azure app timeout. I need to update a lot of records and in the end return some data to the web site in azure. I'm sending batches of 200 requests to update 200 records. I need a faster way to batch update records.
My code:
public static Boolean BulkUpdateNoSorteado(CrmServiceClient service, EntityCollection entities)
{
// Create an ExecuteMultipleRequest object.
var multipleRequest = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
try
{
var countRequest = Int32.Parse(ConfigurationManager.AppSettings["requestCount"]);
// Add a UpdateRequest for each entity to the request collection.
foreach (var entity in entities.Entities)
{
SetStateRequest request = new SetStateRequest
{
EntityMoniker = new EntityReference(entity.LogicalName, entity.Id),
State = new OptionSetValue(1),
Status = new OptionSetValue((int)Domain.Enum.EnumStatusTicket.Nao_sorteado)
};
multipleRequest.Requests.Add(request);
if (multipleRequest.Requests.Count == countRequest || entity == entities.Entities.Last())
{
if (service.OrganizationServiceProxy == null)
{
service = FactoryGetService.AccessTokenGeneratorAsync();
}
ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);
multipleRequest = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
}
}
return true;
}
catch (Exception)
{
throw;
}
}
Try to refactor your code to use:
Parallel.ForEach
, Parallel.For
in C# for example or,EntityCollection
in a concurrent queue (ConcurrentQueue<T>
in C# for example).Here's what the code in 2. might look like:
using System;
using System.Threading;
using System.Data;
using System.Linq;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
public class EntitiesPage : List<Entity> { }
public class MultiThreadedDynamicsCrmUpdate
{
//EntityCollection ec = ...;
//CrmServiceClient service = FactoryGetService.AccessTokenGeneratorAsync();
//int statusOptionSetValue = (int)Domain.Enum.EnumStatusTicket.Nao_sorteado;
int updatesPageSize = 200;
int threadsNumber = 10;
ConcurrentQueue<EntitiesPage> cq = new ConcurrentQueue<EntitiesPage>();
public static void Main(string[] args)
{
UpdateAll();
}
public static void UpdateAll()
{
PaginateEntities(ec);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < threadsNumber; i++)
{
threads.Add(new Thread(UpdateACrmEntitiesPageByThread));
}
foreach (Thread thread in threads)
{
thread.Start();
}
foreach (Thread thread in threads)
{
thread.Join();
}
}
public static void PaginateEntities(EntityCollection ec)
{
EntitiesPage page = new EntitiesPage();
foreach (Entity e in ec.Entities)
{
page.Add(e);
if (page.Count == updatesPageSize)
{
cq.Enqueue(page);
page = new EntitiesPage();
}
}
cq.Enqueue(page);
}
public static void UpdateACrmEntitiesPageByThread()
{
EntitiesPage page = new EntitiesPage();
while (!cq.IsEmpty)
{
if (cq.TryDequeue(out page))
{
var multipleRequest = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
foreach (Entity e in page)
{
SetStateRequest request = new SetStateRequest
{
EntityMoniker = new EntityReference(e.LogicalName, e.Id),
State = new OptionSetValue(1),
Status = new OptionSetValue(...)
};
multipleRequest.Requests.Add(request);
}
ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);
}
}
}
}