プラグインおよびワークフロー アクティビティ内でバッチ要求タイプを使用しないでください
カテゴリ: 使用、信頼性、パフォーマンス
影響の可能性: 中程度
現象
プラグインや同期操作内で発生するワークフロー アクティビティで バッチ リクエスト タイプ を使用すると、ユーザー エクスペリエンスが低下し、タイムアウト エラーが発生する可能性があります。
次のメッセージ リクエスト クラスは、単一のリクエスト内で複数のレコードに対して操作を実行するため、バッチ要求タイプ とみなされます。
- ExecuteMultipleRequest
- ExecuteTransactionRequest
- CreateMultipleRequest
- UpdateMultipleRequest
- UpsertMultipleRequest
ガイダンス
クライアント アプリケーションでこれらのバッチ メッセージを使用して、複数のレコードに対する操作を実行します。 これらのメッセージは、別の操作 (同期ステップ用に登録されたプラグインまたは ワークフロー活動) の実行中に Dataverse が呼び出すコード内で使用しないでください。
さらに具体的には、次のようなシナリオで使用します:
長時間の操作(2 分以上)の実行を意図したデータまたは外部プロセスを一括ロードするには ExecuteMultipleRequest を使用します。
ExecuteMultipleRequest を使用してユーザー定義のクライアントと Dataverse サーバー間のラウンド トリップを最小限に抑え、発生する累積遅延をこれにより短縮します。
操作のバッチを単一のアトミック データベース トランザクションとしてコミットし、例外が発生した場合はロールバックする必要があるクライアントに ExecuteTransactionRequest を使用します。 長期実行トランザクション中はデータベースがブロックされる可能性に注意してください。
同じシナリオで、より高いレベルのスループットを達成するには、一括操作メッセージ (CreateMultipleRequest、 UpdateMultipleRequest、および UpsertMultipleRequest) を使用します。
問題となるパターン
次の例は、プラグインのコンテキストでの 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
メッセージの目的は、高遅延の接続でクライアントとサーバー間のラウンドトリップを最小限に抑えることです。 プラグインはアプリケーション プロセスで直接実行されるか、サンドボックスで隔離されている場合はすぐに近接して実行され、これは遅延はほとんど問題にならないことを意味します。 タイムアウトしきい値の超過を回避し、同期シナリオの対応システムを確保するために、プラグインコードは迅速に実行されブロッキングを最小限に抑える非常に重点を置いた操作である必要があります。 バッチ処理して 1 つの要求として送信するのではなく、各要求を直接送信します。
例: foreach (request in requests) service.Execute(request)
サーバー側では、バッチ要求に含まれる操作は順次実行され、並列には実行されません。 これは次のような場合です ExecuteMultipleSettings.ReturnResponses プロパティが false に設定されます。 開発者は並列処理が可能と想定してこの方法でバッチ要求を使用する傾向があります。 バッチ要求はこの目的を達成しません。
ユーザーは ExecuteTransactionRequest を使用して、各操作がトランザクションに含まれていることを確認します。 プラグインは多くの場合データベース、 トランザクションのコンテキスト内ですでに実行されており、ExecuteTransaction
メッセージを使用する必要がないため、これは同期プラグインステップ内では必要ありません。
関連項目
イベント フレームワーク
ランタイムの制限
.NET 用 SDK を使用して複数の要求を実行する
単一のデータベース トランザクションでメッセージを実行する
注意
ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)
この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。