プラグインおよびワークフロー アクティビティ内でバッチ要求タイプを使用しないでください

カテゴリ: 使用、信頼性、パフォーマンス

影響の可能性: 中程度

現象

プラグインやワークフロー アクティビティのコンテキスト内で ExecuteMultipleRequest または ExecuteTransactionRequest メッセージ要求クラスを使用すると、サンドボックスに分離されたプラグイン タイプが2分間(120000ms) のチャンネル タイムアウト例外にさらされ、同期登録のユーザー エクスペリエンスを低下させる可能性があります。

ガイダンス

ネットワークの遅延によってスループットが低下し、大規模な一括操作の期間が長くなる可能性がある統合シナリオなど、プラットフォーム実行パイプラインの外部でコードが実行されている場合はこれらのバッチ メッセージを使用します。

さらに具体的には、次のようなシナリオで使用します:

  • 長時間の操作(2 分以上)の実行を意図したデータまたは外部プロセスを一括ロードするには ExecuteMultipleRequest を使用します。

  • ExecuteMultipleRequest を使用してユーザー定義のクライアントと Dynamics 365 サーバー間のラウンド トリップを最小限に抑え、発生する累積遅延をこれにより短縮します。

  • 操作のバッチを単一のアトミック データベース トランザクションとしてコミットし、例外が発生した場合はロールバックする必要があるクライアントに ExecuteTransactionRequest を使用します。 長期実行トランザクションの間はデータベースがブロックされる可能性に注意してください。

問題となるパターン

以下はプラグインのコンテキストにおける ExecuteMultipleRequest の使用例です。

警告

このシナリオを回避する必要があります。

public class ExecuteMultipleRequestInPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = factory.CreateOrganizationService(context.UserId);

        QueryExpression query = new QueryExpression("account")
        {
            ColumnSet = new ColumnSet("accountname", "createdon"),
        };

        //Obtain the results of previous QueryExpression
        EntityCollection results = service.RetrieveMultiple(query);

        if (results != null && results.Entities != null && results.Entities.Count > 0)
        {
            ExecuteMultipleRequest batch = new ExecuteMultipleRequest();
            foreach (Entity account in results.Entities)
            {
                account.Attributes["accountname"] += "_UPDATED";

                UpdateRequest updateRequest = new UpdateRequest();
                updateRequest.Target = account;

                batch.Requests.Add(updateRequest);
            }

            service.Execute(batch);
        }
        else return;

    }
}

この例は Execute メソッドで直接型を使用することを含みます。 プラグインまたはワークフロー活動の実行コンテキスト内のどこでも使用できます。 これは同一もしくは個別のクラスに含まれるメソッド内である可能性もあります。 それは Execute メソッド定義に直接含まれることに限定されません。

追加情報

ExecuteMultiple および ExecuteTransaction メッセージはバッチ要求メッセージとみなされます。 高遅延の接続でクライアントとサーバー間のラウンドトリップを最小限に抑えることが目的です。 プラグインはアプリケーション プロセスで直接実行されるか、サンドボックスで隔離されている場合はすぐに近接して実行され、これは遅延はほとんど問題にならないことを意味します。 タイムアウトしきい値の超過を回避し、同期シナリオの対応システムを確保するために、プラグインコードは迅速に実行されブロッキングを最小限に抑える非常に重点を置いた操作である必要があります。 バッチ処理して 1 つの要求として送信するのではなく、各要求を直接送信するだけです。

例: foreach (request in requests) service.Execute(request)

サーバー側では、バッチ要求に含まれる操作は順次実行され、並列には実行されません。 これは次のような場合です ExecuteMultipleSettings.ReturnResponses プロパティが false に設定されます。 開発者は並列処理が可能と想定してこの方法でバッチ要求を使用する傾向があります。 バッチ要求はこの目的を達成しません。 もうひとつの一般的な動機は、各操作がトランザクションに含まれるようにすることです。 プラグインは多くの場合データベース、 トランザクションのコンテキスト内ですでに実行されており、ExecuteTransaction メッセージを使用する必要がないため、これは必要ありません。

関連項目

イベント フレームワーク
ランタイムの制限
組織サービスを使用して複数の要求を実行する
単一のデータベース トランザクションでメッセージを実行する

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。