知識創造研究室 by CRM(xRM)

CRMリーディングカンパニーである アーティサン株式会社 CRM事業部 の最先端 CRM ブログです。

Dynamics 365(Dynamics CRM)Web API レコード取得編 Part.Ⅴ

time 2017/08/27

みなさん、ちゃーっす!
夏バテで『ピノ チョコアソート』を食べ倒してる Harada です。
アーモンドが一番好きです!(*`・へ・´*)ドヤァ

さて、今回はご要望頂きましたレコード取得時のページングとFetchXML の実行とページングについて書かせてもらおうと思います。

Dynamics 365 レコード取得 ページング

Web API でレコードを取得する場合、ページングをしない場合は最大5,000件という制限があります。取得するフィールド数や処理する側のスペックにもよりますが、一度に5,000件取得するとクライアント側の処理に時間がかかり、パフォーマンスの問題となることがあります。
そこで、ページングが必要となります。ページングとは、5,000件のデータを1,000件ずつ5回取得することを言います。
なんとなくページングについてご理解いただけましたか?理解できた方も理解できなかった方も下記のサンプルを確認してください(笑)

var apiUrl = "https://<ORG>.crm7.dynamics.com/api/data/v8.2/incidents";
var s = '$select=casetypecode,checkemail,_customerid_value,description,';
s += 'exchangerate,followupby,influencescore,numberofchildincidents,';
s += '_owninguser_value,statecode,statuscode,ticketnumber,title,versionnumber';
// 実行
execute(encodeURI(apiUrl + '?' + s));

function execute(requestUrl) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", requestUrl, true);
  xhr.setRequestHeader('Accept', 'application/json');
  xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
  xhr.setRequestHeader('OData-MaxVersion', '4.0');
  xhr.setRequestHeader('OData-Version', '4.0');
  // 1ページあたりのレコード数を指定
  xhr.setRequestHeader('Prefer', 'odata.include-annotations="*",odata.maxpagesize=10');
  xhr.onreadystatechange = function () {
    if (this.readyState == 4) {
      if (this.status == 200) {
        console.log(this.response);
        var data = JSON.parse(this.response);
        // さらにレコードがある場合に再帰
        if (data["@odata.nextLink"])
          execute(data["@odata.nextLink"]);
      } else {
        var error = JSON.parse(this.response).error;
        Xrm.Utility.alertDialog(error.message, function () { });
      }
    }
  };
  xhr.send();
}

さて、以前までの分と何が違うのでしょうか・・・簡単に説明します。

1行目 ~ 4行目
レコード取得のURLを作成しています。ここは、以前と変わりないですね。
6行目
この行の下で定義している function を呼び出しています。
16行目
1度に取得するレコード数を指定しています。ここでは1度のリクエストで10件返すように指定しています。
23行目、24行目
さらにレコードがあるかどうかは、戻ってきたデータ『@odata.nextLink』にURLが入っているためこちらで再度リクエストします。

意外と簡単だと思いませんか?ただ、ページ番号を指定して取得することが簡単にできそうにないという点が残念です。

Dynamics 365 レコード取得 FetchXMLの実行

つづいて、以前簡単に触れたFetchXMLの実行です。FetchXMLなので、集計にしようかと思ったのですが、ページングのほうが難しそうだったので、ここではFetchXMLでのページングのサンプルを記載します。それではご覧あれ~!

var apiUrl = "https://<ORG>.crm7.dynamics.com/api/data/v8.2/incidents";
var page = 1; // ページを指定
var count = 10; // 1ページあたりのレコード数を指定
// fetch エレメント の子エレメントを定義
var xml = '<entity name="incident" ><attribute name="ticketnumber" />';
xml += '<attribute name="title" /><attribute name="exchangerate" />';
xml += '<attribute name="checkemail" /><attribute name="casetypecode" />';
xml += '<attribute name="statuscode" /><attribute name="versionnumber" />';
xml += '<attribute name="owninguser" /><attribute name="customerid" />';
xml += '<attribute name="statecode" /><attribute name="numberofchildincidents" />';
xml += '<attribute name="followupby" /><attribute name="influencescore" />';
xml += '<attribute name="description" /></entity>';
// 実行
executeFetchXml(apiUrl, xml, page, count);

function executeFetchXml(apiUrl, fetch, page, count, pagingCookie) {
  // fetchXml を作成
  var fetchXml = 'fetchXml=<fetch';
  fetchXml += ' page="' + page + '"';
  fetchXml += ' count="' + count + '"';
  if (pagingCookie) {
    fetchXml += " " + escape(pagingCookie);
  }
  fetchXml += '>' + fetch + '</fetch>';

  var xhr = new XMLHttpRequest();
  xhr.open("GET", encodeURI(apiUrl + "?" + fetchXml), true);
  xhr.setRequestHeader('Accept', 'application/json');
  xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
  xhr.setRequestHeader('OData-MaxVersion', '4.0');
  xhr.setRequestHeader('OData-Version', '4.0');
  // ページング用の注釈を指定。
  xhr.setRequestHeader('Prefer', 'odata.include-annotations="*"');
  xhr.onreadystatechange = function () {
    if (this.readyState == 4) {
      if (this.status == 200) {
        console.log(this.response);
        var data = JSON.parse(this.response);
        // さらにレコードがある場合に再帰
        var cookies = data["@Microsoft.Dynamics.CRM.fetchxmlpagingcookie"];
        if (cookies) {
          page++;
          pagingCookie = getPagingCookie(cookies);
          executeFetchXml(apiUrl, fetch, page, count, pagingCookie);
        }
      } else {
        var error = JSON.parse(this.response).error;
        Xrm.Utility.alertDialog(error.message, function () { });
      }
    }
  };
  xhr.send();
}

function getPagingCookie(pagingCookies) {

  var div = document.createElement('div');
  div.innerHTML = pagingCookies;
  var pageNumber = div.firstChild.attributes.pagenumber.value;
  var pagingcookie = div.firstChild.attributes.pagingcookie.value;
  pagingcookie = unescape(unescape(pagingcookie));
  pagingcookie = pagingcookie.replace(/</g,'&lt;').replace(/>/g,'&gt;');
  pagingcookie = pagingcookie.replace(/\"/g,'\'').replace(/\'/g,'&'+'quot;');

  return "paging-cookie='" + pagingcookie + "'";
}

なかなか厄介でした。。。ページングをするには<fetch>エレメントを変更していく必要があるので、ややこしくなりますね。それでは説明です。

1行目
Web API のURLなので説明は不要ですね。
2行目
取得するページ番号を指定しています。
3行目
取得するレコード数を指定しています。
5行目 ~ 12行目
FetchXMLの<entity>以下を指定しています。
18行目 ~ 24行目
<fetch>エレメントにページングの設定を行っています。
33行目
ページングに使用する『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』を取得するために注釈の指定が必要です。(ちょっと調べたのですが”*”でなく、単体で取得する注釈がわかりませんでした。。)
41行目 ~ 43行目
さらにレコードがあるかどうかは、戻ってきたデータ『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』があるかどうかで判定し、再帰で呼び出すためにページ番号、クッキーを再設定しています。
55行目
『getPagingCookie』では『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』で取得した文字列からpagingcookie属性の値の取得を行っています。『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』には下記のような文字列が設定されています。

<cookie pagenumber="2" pagingcookie="%253ccookie%2520page%253d%25223%2522%253e%253cincidentid%2520last%253d%2522%257bE384A5B4-498A-E711-8118-C4346BC53068%257d%2522%2520first%253d%2522%257bD184A5B4-498A-E711-8118-C4346BC53068%257d%2522%2520%252f%253e%253c%252fcookie%253e" istracking="False" />

FetchXMLでのページングはこんな感じです。いかがですか?参考になりますでしょうか。私は疲れました(笑)


今回、はじめてFetchXMLでのページングを実装したのですが、『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』で返される cookie の中に pagenumber があるのでその値をインクリメントすればいいと思ってやっていたんですが・・・正しい値が返ってこず苦戦しました(笑)
このように実装してみないとわからないことがあるのが Dynamics 365 の醍醐味ですね。
次回は・・・・って何も考えてなかったw 何かしら有益な情報をかけるようにネタを探しておきますm(_ _)m

※ 記事の内容は個人発信の参考情報です。記事内容のご利用は、ご自身の判断でお願いします。

The following two tabs change content below.

Kengo Harada

CRM事業部 製品開発部 マネージャーアーティサン株式会社

文系プログラマ(.NET Framework、Java)。25歳から始めたプログラムは死ぬ気で頑張った(誰も褒めてくれないので自分で誉めてます)。気が付けば製品開発部のマネージャー・・・
弊社Dynamics CRM トレーニングの講師をやったりもします。
事業部やら役職やらありますが、『事業部内の便利屋』が一番フィットする肩書です。

<アーティサン株式会社 CRM製品>

CRM製品に関するお問い合わせ TEL 042-444-4815

メールでお問い合わせはこちら

down

コメントする