Dynamics CRM Online 2015 Update 1 SDK 新機能: 変更されたレコードの一括取得

みなさん、こんにちは。

今回は Dynamics CRM Online 2015 Update 1 で提供されるプラット
フォームと SDK の新機能より、変更されたレコードの一括取得に
ついて紹介します。

概要

Dynamics CRM 上のレコードをマスターとして外部システムと連携
する場合、前回取得したデータセットからの差分のみを取得すべき
ですが、これまではそのような機能が提供されていませんでした。
※メタデータの差分取得は提供済み

このような要望を満たすため、今回のリリースではレコードの差分
取得がサポートされます。

動作確認

今回は取引先企業データを外部に連携するシナリオを考えます。

プログラムの作成

1. Visual Studio を起動します。新しいプロジェクトをクリック
して、Visual C# | Windows デスクトップ | コンソールアプリ
ケーションを選択します。.NET Framework 4.5.2 を指定します。
任意の名前を付けて、「OK」をクリックします。

image

2. ソリューションエクスプローラーより作成したプロジェクトを
右クリックして、NuGet パッケージの管理をクリックします。

image

3. 左ペインで「オンライン」を選択後、右上の検索ボックスにて
crmsdk を検索します。一覧より Microsoft Dynamics CRM 2015
SDK client and portal assemblies を選択して、「インストール」を
クリックします。

image

4. インストールが完了したら「閉じる」で NuGet パッケージの
管理を閉じます。

5. Main メソッドに以下のコードを追加します。これで Dynamics
CRM 組織への接続が作成できます。接続文字は適宜変更します。

CrmConnection conn = CrmConnection.Parse("Url=https://contoso.crm.dynamics.com; Username=someone@contoso.onmicrosoft.com; Password=password;");
OrganizationService service = new OrganizationService(conn);

6. 差分取得時に渡すトークンを格納する文字列型変数を定義します。
また取得したデータを格納するリストを定義します。

string token;
List<Entity> initialrecords = new List<Entity>();

7. 以下のコードを追加して、既存の取引先企業を取得します。

// 差分要求の作成
RetrieveEntityChangesRequest request = new RetrieveEntityChangesRequest();
// クエリの指定
request.EntityName = "account";
request.Columns = new ColumnSet("name");
// ページングの指定
request.PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false };

8. 以下のコードを追加してデータを取得します。尚、既定で
一度の要求で取得できるレコード数が 5000 件のため while
ループでページングします。RetrieveEntityChangesResponse
の EntityChanges には追加/更新されたレコードと削除された
レコードの情報が含まれます。以下のコードは初回実行時と
想定しているため、追加/更新のみを確認しています。

while (true)
{
    // 差分データの取得
    RetrieveEntityChangesResponse response = (RetrieveEntityChangesResponse)service.Execute(request);

    // 取得したデータをリストに保存
    initialrecords.AddRange(response.EntityChanges.Changes.Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray());
    // ページングが完了したら、次回差分取得のためのトークンを確保
    if (!response.EntityChanges.MoreRecords)
    {                   
        token = response.EntityChanges.DataToken;
        break;

    }
    // まだレコードがある場合はページング処理
    request.PageInfo.PageNumber++;
   request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie;
}

initialrecords.ForEach(x => Console.WriteLine("Record {0} added", x["name"]));
Console.Read();

9. 次に差分取得のコードを追加します。利用するクエリは同じですが、
DataVersion に前回取得したトークンを指定しています。また今回は
差分取得しているため、削除されたレコードも確認しています。削除
されたレコードは Guid しかデータが無いため、EntityReference 型と
なります。

RetrieveEntityChangesRequest changerequest = new RetrieveEntityChangesRequest();
changerequest.EntityName = "account";
changerequest.Columns = new ColumnSet("name", "accountnumber", "telephone1");
changerequest.PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false };
// 前回取得したトークンを指定
changerequest.DataVersion = token;

// 追加/更新したレコードのリストを作成
List<Entity> neworupdatedrecords = new List<Entity>();
// 削除されたレコードのリストを作成
List<EntityReference> removedrecords = new List<EntityReference>();
while (true)
{
    RetrieveEntityChangesResponse response = (RetrieveEntityChangesResponse)service.Execute(changerequest);

    // 結果より追加/更新されたものだけを処理
    neworupdatedrecords.AddRange(response.EntityChanges.Changes.Where(x=>x.Type == ChangeType.NewOrUpdated).Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray());
    // 結果より削除されたものだけを処理
    removedrecords.AddRange(response.EntityChanges.Changes.Where(x=>x.Type == ChangeType.RemoveOrDeleted).Select(x => (x as RemovedOrDeletedItem).RemovedItem).ToArray());

    if (!response.EntityChanges.MoreRecords)
    {
        token = response.EntityChanges.DataToken;
        break;
    }
    // ページング処理
    request.PageInfo.PageNumber++;
   request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie;
}

neworupdatedrecords.ForEach(x => Console.WriteLine("Record {0} added or updated", x["name"]));
removedrecords.ForEach(x => Console.WriteLine("Record {0} removed", x.Id));

Console.Read();

プログラムの実行

1. F5 キーを押下してプログラムを実行します。

2. データの結果を確認します。

image

3. プログラムをそのままにして、ブラウザからレコードの追加
更新と削除を行います。今回は「テスト取引先企業」の追加、
「フォース コーヒー」の変更、「リビングウェア」の削除を
行いました。

4. プログラムに戻って Enter キーを押下します。意図した結果
になることを確認します。

image

まとめ

変更されたレコードの一括取得を行うことで、効率的にデータ
同期を行えます。尚、特定のレコードが前回取得以降に複数回
更新された場合も、詳細の履歴はわからず、最新の情報だけが
取得できます。

是非お試しください。

- 中村 憲一郎