使用 ExecuteMultiple 提高批量数据加载的性能

 

发布日期: 2017年1月

适用于: Dynamics 365 (online),Dynamics 365 (on-premises),Dynamics CRM 2016,Dynamics CRM Online

您可以使用 ExecuteMultipleRequest 消息在 Microsoft Dynamics 365(在线或本地)中支持更高吞吐批量消息传递方案,尤其在 Internet 延迟可能是最大限制因素的 Microsoft Dynamics 365 (online) 中。ExecuteMultipleRequest 接受消息 Requests输入集合,按消息请求在输入集合中出现的顺序执行每个消息请求,还可以返回包含发生的每个消息的响应或错误的Responses 的集合。 输入集合中的每个消息请求都在单独的数据库事务中进行处理。 使用 IOrganizationService执行ExecuteMultipleRequestExecute 方法。

通常,ExecuteMultipleRequest 的行为与您在输入请求集合中单独执行每个消息请求时相同,但性能更高。 提倡使用服务代理的 CallerId 参数,它适用于执行输入请求集合中的每个消息。 当您期望处理每个消息时,执行插件和工作流活动。

插件和自定义工作流活动形式的自定义代码甚至可以执行 ExecuteMultipleRequest。 不过,需要记住一些要点。 同步注册的插件引发的异常在响应集合项 Fault 参数中返回。 如果插件在数据库事务内部执行,插件执行 ExecuteMultipleRequest,且启动事务回滚,则回滚包括 ExecuteMultipleRequest 执行请求导致的所有数据更改。

本主题内容

示例

指定运行时执行选项

运行时限制

处理批量大小错误

示例

以下示例代码演示执行多个创建操作的单一 ExecuteMultipleRequest。 称作设置的运行时执行选项用于控制请求处理和返回的结果。 下一节将讨论这些运行时选项。


// Get a reference to the organization service.
using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri,serverConfig.Credentials, serverConfig.DeviceCredentials))
{
    // Enable early-bound type support to add/update entity records required for this sample.
    _serviceProxy.EnableProxyTypes();

    #region Execute Multiple with Results
    // Create an ExecuteMultipleRequest object.
    requestWithResults = 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()
    };

    // Create several (local, in memory) entities in a collection. 
    EntityCollection input = GetCollectionOfEntitiesToCreate();

    // Add a CreateRequest for each entity to the request collection.
    foreach (var entity in input.Entities)
    {
        CreateRequest createRequest = new CreateRequest { Target = entity };
        requestWithResults.Requests.Add(createRequest);
    }

    // Execute all the requests in the request collection using a single web method call.
    ExecuteMultipleResponse responseWithResults =
        (ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);

    // Display the results returned in the responses.
    foreach (var responseItem in responseWithResults.Responses)
    {
        // A valid response.
        if (responseItem.Response != null)
            DisplayResponse(requestWithResults.Requests[responseItem.RequestIndex], responseItem.Response);

        // An error has occurred.
        else if (responseItem.Fault != null)
            DisplayFault(requestWithResults.Requests[responseItem.RequestIndex], 
                responseItem.RequestIndex, responseItem.Fault);
    }

' Get a reference to the organization service.
_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig)

Using _serviceProxy
    ' Enable early-bound type support to add/update entity records required for this sample.
    _serviceProxy.EnableProxyTypes()

    '#Region "Execute Multiple with Results"
    ' Create an ExecuteMultipleRequest object.
    ' Assign settings that define execution behavior: continue on error, return responses.
    ' Create an empty organization request collection.
    requestWithResults = New ExecuteMultipleRequest() With
        {
            .Settings = New ExecuteMultipleSettings() With
                        {
                            .ContinueOnError = False,
                            .ReturnResponses = True
                        },
            .Requests = New OrganizationRequestCollection()
        }

    ' Create several (local, in memory) entities in a collection. 
    Dim input As EntityCollection = GetCollectionOfEntitiesToCreate()

    ' Add a CreateRequest for each entity to the request collection.
    For Each entity In input.Entities
        Dim createRequest_Renamed As CreateRequest = New CreateRequest With {.Target = entity}
        requestWithResults.Requests.Add(createRequest_Renamed)
    Next entity

    ' Execute all the requests in the request collection using a single web method call.
    Dim responseWithResults As ExecuteMultipleResponse =
        CType(_serviceProxy.Execute(requestWithResults), ExecuteMultipleResponse)

    ' Display the results returned in the responses.
    For Each responseItem In responseWithResults.Responses

        If responseItem.Response IsNot Nothing Then
            ' A valid response.
            DisplayResponse(requestWithResults.Requests(responseItem.RequestIndex),
                            responseItem.Response)

        ElseIf responseItem.Fault IsNot Nothing Then
            ' An error has occurred.
            DisplayFault(requestWithResults.Requests(responseItem.RequestIndex),
                         responseItem.RequestIndex, responseItem.Fault)
        End If
    Next responseItem

若要查看完整示例,请参阅示例:执行多个请求

指定运行时执行选项

ExecuteMultipleRequestSettings 参数适用于控制执行行为和返回结果的请求集合中的所有请求。 我们更详细地看一下这些选项。

ExecuteMultipleSettings 成员

说明

ContinueOnError

当为 true 时,继续处理集合中的下一个请求,即使从集合中当前请求的处理中返回错误。 当为 false 时,不要继续处理下一个请求。

ReturnResponses

当为 true 时,从处理的每个消息请求返回响应。 当为 false 时,不返回响应。

如果设置为 true 且请求不返回一个响应,由于这是其设计,因此该请求的 ExecuteMultipleResponseItem 设置为 null

不过,即使为 false,如果返回错误, Responses 程序集将不为空。 如果返回错误,则每个已处理请求的集合中将有一个响应项返回错误,Fault 将设置为发生的实际错误。

例如,在包含六个请求的请求集合中(第三个和第五个请求返回错误),下表说明了 Responses 集合将包含的内容。

设置

响应集合内容

ContinueOnError=true,ReturnResponses=true

6 个响应项:2 个将 Fault 设置为值。

ContinueOnError=false,ReturnResponses=true

3 个响应项:1 个将 Fault 设置为值。

ContinueOnError=true,ReturnResponses=false

2 个响应项:2 个将 Fault 设置为值。

ContinueOnError=false,ReturnResponses=false

1 个响应项:1 个将 Fault 设置为值。

响应项中的 RequestIndex 参数表示响应关联的请求的序列号(从零开始)。 在上述示例中,第三个请求的请求索引为 2。

运行时限制

对于 ExecuteMultipleRequest 的使用,有一些限制,如下表所述。

  • 不允许递归 - ExecuteMultipleRequest 不能调用 ExecuteMultipleRequest。 请求集合中的 ExecuteMultipleRequest 将生成该请求项的错误。

  • 最大批量大小 – 对于可添加到请求集合的请求数量,存在一定限制。 如果超过该限制,则在执行第一个请求后引发错误。 尽管可以为 Microsoft Dynamics 365 部署设置最大数量为 1000 个请求,但是通常限制 1000 个请求。 此限制的部署设置为 BatchSize

  • 并行呼叫限制 – 对于 Microsoft Dynamics 365 (online),每个组织限制为有 2 个并发 ExecuteMultipleRequest 执行。 如果超过该限制,则在执行第一个请求后引发“服务器忙”错误。 对于内部部署,默认情况下不启用限制。 此限制的部署设置为 ExecuteAsyncPerOrgMaxConnectionsPerServer

    提示

    对于所有 Dynamics 365 部署,部署管理员可以设置或更改限制。

处理批量大小错误

当输入请求集合超出最大批量大小时,应怎么办? 您的代码无法直接通过部署 Web 服务查询最大批量大小,除非它在具有部署管理员角色的帐户下运行。

幸运的是,您可以使用另一种方法。 在输入 Requests 集合中的请求数超出组织允许的最大批量大小时,会从 ExecuteMultipleRequest 调用返回错误。 最大批量大小在错误中返回。 您的代码可以检查该值,将输入请求集合调整到指示的限制范围内,然后重新提交 ExecuteMultipleRequest。 以下代码段演示该逻辑的一些部分。


catch (FaultException<OrganizationServiceFault> fault)
{
    // Check if the maximum batch size has been exceeded. The maximum batch size is only included in the fault if it
    // the input request collection count exceeds the maximum batch size.
    if (fault.Detail.ErrorDetails.Contains("MaxBatchSize"))
    {
        int maxBatchSize = Convert.ToInt32(fault.Detail.ErrorDetails["MaxBatchSize"]);
        if (maxBatchSize < requestWithResults.Requests.Count)
        {
            // Here you could reduce the size of your request collection and re-submit the ExecuteMultiple request.
            // For this sample, that only issues a few requests per batch, we will just print out some info. However,
            // this code will never be executed because the default max batch size is 1000.
            Console.WriteLine("The input request collection contains %0 requests, which exceeds the maximum allowed (%1)",
                requestWithResults.Requests.Count, maxBatchSize);
        }
    }
    // Re-throw so Main() can process the fault.
    throw;
}

Catch fault As FaultException(Of OrganizationServiceFault)

    ' Check if the maximum batch size has been exceeded. The maximum batch size is only included in the fault if it
    ' the input request collection count exceeds the maximum batch size.
    If fault.Detail.ErrorDetails.Contains("MaxBatchSize") Then

        Dim maxBatchSize As Integer = Convert.ToInt32(fault.Detail.ErrorDetails("MaxBatchSize"))
        If maxBatchSize < requestWithResults.Requests.Count Then
            ' Here you could reduce the size of your request collection and re-submit the ExecuteMultiple request.
            ' For this sample, that only issues a few requests per batch, we will just print out some info. However,
            ' this code will never be executed because the default max batch size is 1000.
            Console.WriteLine("The input request collection contains %0 requests, which exceeds the maximum allowed (%1)", requestWithResults.Requests.Count, maxBatchSize)
        End If
    End If
    ' Re-throw so Main() can process the fault.
    Throw
End Try

另请参阅

Execute
OrganizationRequest
OrganizationResponse
使用组织服务读取和写入数据或元数据
组织服务中的 xRM 消息
Discovery Service 中的消息
组织服务中的 Dynamics 365 消息
导入数据

Microsoft Dynamics 365

© 2017 Microsoft。 保留所有权利。 版权