【C#】【Dynamics CRM】QueryExpression によるページングの指定
Dynamics CRM から組織サービス経由で大量のデータを取得(RetrieveMultiple)する場合、標準で取得件数5000件制限が付与されています。
予めフィルターしたデータを取得するのであれば、あまり問題にはなりませんが、 5000件を超えるデータを取得することが予想される場合、何かした対応をしておかないといけません。
対応方法
対応方法としては以下のものが考えられます。
- Filter条件でTop、Underを指定し、データ取得を回す。
- RetrieveMultipleのQueryにページングの設定をして、データ取得を回す。
- Dynamics CRM オンプレミスのレジストリを弄って、取得上限件数を上げる。
手法としては【1.】でも可能ですが、Dynamics CRM ではページングという機能が推奨されている感じなので【2.】がいいと思います。
【3.】は最終手段的な感じですが、要件次第では……。という感じでしょうか。
参考URL
PageInfoクラス
QueryExpressionクラスのPageInfoプロパティを設定することで利用可能です。
PagingInfo のメンバー
PagingInfo のメンバー (Microsoft.Xrm.Sdk.Query)
重要なメンバーは下記3つ ・Count ・PageNumber ・PagingCookie
【Count】は一度のRetrieveMultipleで取得してくるレコードの件数(1ページにおける件数)を指定します。 これはどちらにしても最大5000件までしか指定できません。
【PageNumber】は取得してくるデータセットの番号になっており、ここを繰り上げることで、Countで指定した件数を繰り上げて取得していくことができます。 今回Countは"5000"なので、1ページ目は1~5000、2ページ目は5001~10000、といった形で取得してくることになります。
【PagingCookie】は一度取得してきたデータの最初と最後のGUIDを明示的に指定しているXMLです。
コード
今回のコードでは、通常のQueryExpressionとページングを利用したQueryExpressionとでメソッドを分けてみました。
using System; using Microsoft.Xrm.Client; using Microsoft.Xrm.Client.Services; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; namespace MyProject.CrmGetAllRecord { class Program { static void Main(string[] args) { var connection = CrmConnection.Parse("Url=https://***.crm7.dynamics.com; Username=***@***.onmicrosoft.com; Password=***;"); var service = new OrganizationService(connection); Console.WriteLine("Start Get All Entity Collection"); EntityCollection collection1 = GetAllEntityCollection("account",service); EntityCollection collection2 = GetAllEntityCollectionNomal("account", service); Console.WriteLine("Get Collection Data. Set Page Info Properties : {0}", collection1.Entities.Count); Console.WriteLine("Get Collection Data. Nomal Type : {0}", collection2.Entities.Count); Console.ReadKey(); } /// <summary> /// QueryExpression により通常取得 /// </summary> /// <param name="EntityName"></param> /// <param name="service"></param> /// <returns></returns> private static EntityCollection GetAllEntityCollectionNomal( string EntityName,OrganizationService service) { QueryExpression query = new QueryExpression(); query.EntityName = EntityName; query.ColumnSet.AddColumn(EntityName + "id"); return service.RetrieveMultiple(query); } /// <summary> /// QueryExpressionでPageに関するparameterを設定 /// </summary> /// <param name="EntityName"></param> /// <param name="service"></param> /// <returns></returns> private static EntityCollection GetAllEntityCollection(string EntityName, OrganizationService service) { QueryExpression query = new QueryExpression(); query.EntityName = EntityName; query.ColumnSet.AddColumn(EntityName + "id"); query.PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, PagingCookie = null }; EntityCollection returnCollection = new EntityCollection(); // MoreRecords が Falseになるまで、PageNumberを増やしてRetrieveMultipleし続ける。 while (true) { EntityCollection results = service.RetrieveMultiple(query); if (results.Entities != null) { returnCollection.Entities.AddRange(results.Entities); } if (results.MoreRecords) { query.PageInfo.PageNumber++; query.PageInfo.PagingCookie = results.PagingCookie; } else { break; } } return returnCollection; } } }
結果画面