如何减少 Dynamics 365 中多个请求的执行时间

How to decrease the execution time of multiple requests in Dynamics 365

我有大麻烦了。我在代码中的多个请求的执行时间比 azure 应用程序超时时间长。我需要更新很多记录,最后 return 将一些数据更新到 Azure 网站。我正在发送 200 个请求来更新 200 条记录。我需要一种更快的方式来批量更新记录。

我的代码:

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;
    }
}

尝试重构您的代码以使用:

  1. 并行编程(如 C# 中的 Parallel.ForEachParallel.For for example
  2. Pure multi-threading 因此让多个工作线程同时协作处理多个更新。在这方面,您可以在并发队列中共享 EntityCollection(C# for example 中的 ConcurrentQueue<T>)。
    如果在解决方案中配置线程数和多个更新的批大小,可以更轻松地测试 Azure 超时。
  3. 线程的尽可能多的 CRM 组织 URL。

下面是 2. 中的代码:

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);
            }
        }
    }
}