【C#】【Dynamics CRM】ExecuteMultipleRequestによる一括実行
Dynamics CRMにおいて、C#などの外部プログラムでCUD操作を行う際、基本的に1件ずつレコードを処理する形になります。
ですが、ExecuteMultipleRequestクラスを利用することで、Dynamics CRM各Execute Messageの一括実行が可能になります。
これが意外と性能的にもよかったので、書き留めておきたいと思います。
通常アプローチ
以下の【NomalRecordCreate】メソッドでは、パラメータのcountの数だけ、アカウントレコードを作成するというものです。
forなりforeachなりで、OrganizationServiceのCreateメソッドを回しまくるという、単純な力技アプローチです。
もちろん、各操作のログの確保やシーケンス的なものの制御を意識するのであれば、こちらのほうが望ましい場合もあるかと思います。
/// <summary> /// 通常の作成方法 /// </summary> /// <param name="service"></param> static void NomalRecordCreate(OrganizationService service, int count) { Console.WriteLine("Nomal Create Start!"); Entity account = new Entity("account"); for (int i = 0; i < count; i++) { account["name"] = "Nomal Create" + i; service.Create(account); } }
以下ではExecuteMultipleRequestを利用した形を記載してみます。
ExecuteMultipleRequest実施概要
実行概要を簡単に説明しますとExecuteMultipleRequestインスタンスを生成し、各プロパティにリクエストインスタンスを登録。 最終的にOrganizationService.Executeメソッドにパラメータとして上記インスタンスを渡すというものです。
ExecuteMultipleRequestクラスのメンバーは以下のとおり。
■ExecuteMultipleRequest のメンバー
ExecuteMultipleRequest のメンバー (Microsoft.Xrm.Sdk.Messages)
今回使用する、というか基本的に抑えておくべきプロパティは [Settings] [Requests] の2つのパラメータです。
【Settings】パラメータにはエラー時などにおける要求処理方法を設定するExecuteMultipleSettingsインスタンスを設定します。
このへんは後々試してみたいと思うので、以下のとおりMSDNから引用しておきます。
■ExecuteMultipleSettings のメンバー ContinueOnError trueの場合、コレクションの次の要求の処理を続けます。フォールトがコレクションの現在の要求の処理から戻されている場合でもそうです。false場合、次の要求は処理し続けません。
■ReturnResponses trueの場合、処理された各メッセージ要求から応答を戻します。falseの場合、応答は返されません。 trueに設定され、要求が応答を戻さない場合、そのような設計なので、その要求の ExecuteMultipleResponseItem は nullに設定されます。 しかし、エラーが返された場合、false、Responses のコレクションは空ではなくなります。エラーが返された場合、フォールトを返した処理された各要求のコレクションに1つの応答アイテムがあり、Faultは発生した実際のフォールトに設定されます。
【Requests】には実際にどのDynamics CRM Message Requestを実行するかを設定します。 OrganizationRequestCollectionインスタンスを生成し、そこに【Microsoft.Xrm.Sdk.Messages】名前空間のCreateRequestなどのRequestClassを登録していきます。
■Microsoft.Xrm.Sdk.Messages 名前空間
Microsoft.Xrm.Sdk.Messages 名前空間
コード例
実際のコード例です。
/// <summary> /// ExecuteMultipleRequestでの作成方法 /// </summary> /// <param name="service"></param> public static void ExecuteMultipleRecordCreate(OrganizationService service ,int count) { Console.WriteLine("ExecuteMultipleRequest Start!"); var request = new ExecuteMultipleRequest() { Settings = new ExecuteMultipleSettings() { ContinueOnError = false, ReturnResponses = true }, Requests = new OrganizationRequestCollection() }; Entity account = new Entity("account"); for (int i = 0; i < count; i++) { account["name"] = "ExecuteMultipleRequest Create" + i; request.Requests.Add(new CreateRequest { Target = account }); } ExecuteMultipleResponse responseWithResults = (ExecuteMultipleResponse)service.Execute(request); }
ExecuteMultipleRequestの制約
一見便利そうなExecuteMultipleRequestですが、以下のMSDNからの引用のように制限がいくつか存在します。
■ランタイムの制限 以下のリストで示すように、ExecuteMultipleRequest の使用に関する、いくつかの制限があります。
再帰は許可されません - ExecuteMultipleRequest では ExecuteMultipleRequestを起動できません。要求コレクションで見つかる ExecuteMultipleRequest は、その要求アイテムに関するエラーを生成します。
最大バッチ サイズ - 要求コレクションに追加できる要求の数には制限があります。この制限を超えると、最初の要求が実行される前にフォールトがスローされます。Microsoft Dynamics CRM展開に最大数を設定できますが、1000 個の制限が一般的です。この上限の展開設定は、BatchSizeです。
同時呼び出しの調整 - Microsoft Dynamics CRM Online の場合、組織ごとに ExecuteMultipleRequest 2 人の同時実行の制限があります。この制限を超えると、最初の要求が実行される前に "サーバー ビジー" フォールトがスローされます。設置型展開の場合、既定では調整が有効ではありません。この上限の展開設定は、ExecuteAsyncPerOrgMaxConnectionsPerServerです。
この中で一番ボトルネックとなるのは【最大バッチサイズ】の部分かと思います。 デフォルトでは1000件までのRequestとなっており、上記コードでも【ExecuteMultipleRecordCreate】のcountパラメータに1000以上を指定するとエラーが帰ってきます。
この辺りはうまくプログラムを調整しなければ利用できないですね……。
一応Serverであれば変更可能? のようですが、こう言う数値系はもっぱら変更しないほうが、身のためかなぁという経験則です……。
参考URL
■MSDN
大量データ負荷でパフォーマンスを向上させる ExecuteMultiple を使用する
■Dynamics CRM Team Blog