Web API CDSWebApiService の並列操作のサンプル (C#)
注意
エンティティとテーブルの違いがわかりませんか? Microsoft Dataverse で「開発者: 用語を理解する」を参照してください。
この例では、System.Threading.Tasks.Parallel.ForEach Method のループを使用して、Dataverse で作成するテーブル行 (エンティティ レコード) のセットに対してデータ並列処理を可能にする方法を示しています。
このサンプルでは、操作内で CDSWebApiService クラスの同期メソッドを使用します。 CDSWebApiService クラスは、Service Protection API の制限を管理できるため、このコードは、クライアントが予期する一時的な 429 エラーに対して回復性があります。 構成可能な回数再試行します。
詳細:
このサンプルは、 単純な Parallel.ForEach ループを作成する方法 に記載の例をベースに、CDSWebApiService クラスが提供する同期メソッドを使用して Dataverse エンティティの作成と削除の操作を実行するように変更したものです。
注意
Fiddler を使って予想されるサービス保護 API の制限を監視する場合は、作成する行数を 10,000 行程度に設定する必要があります。 5 分後に表示され始めます。 アプリケーションが失敗を再試行し、すべての行のフローを完了させる様子に注意してください。
前提条件
以下は CDSWebApiService C# サンプルの構築および実行に必要です。
- Microsoft Visual Studio 2019。
- CRUD 操作を実行する特権を用いて Microsoft Dataverse にアクセスします。
このサンプルを実行する方法
PowerApps - サンプル GitHub リポジトリに移動して、サンプル リポジトリをクローンもしくはダウンロードし、ローカル フォルダに内容を解凍してください。
リポジトリ フォルダ cds/webapi/C#/ParallelOperations に移動し、Visual Studio で ParallelOperations.sln ファイルを開きます。
ソリューション エクスプローラー の ParallelOperations プロジェクトで、App.config ファイルを開きます。 これは、すべての Web API C# サンプルで使用される共有アプリケーション構成ファイルです。 このファイルを編集した後は、サンプルの実行に使用する環境またはログオンを変更しない限り、ファイルを再編集する必要はありません。
Url、UserPrincipalName、とPasswordの値を編集して、接続する Dataverse インスタンスと資格情報を設定する必要があります。<add name="Connect" connectionString="Url=https://yourorg.api.crm.dynamics.com; Authority=null; ClientId=51f81489-12ee-4a9e-aaae-a2591f45987d; RedirectUrl=app://58145B91-0C36-4500-8554-080854F2AC97; UserPrincipalName=you@yourorg.onmicrosoft.com; Password=y0urp455w0rd; CallerObjectId=null; Version=9.1; MaxRetries=3; TimeoutInSeconds=180; "/>ParallelOperations プロジェクトがスタートアップ プロジェクトとして設定されていることを確認します。 プロジェクトの名前は、スタートアップ プロジェクトであることを示すために太字にする必要があります。 名前が太字でない場合は、ソリューション エクスプローラーでその名前を右クリックして、スタートアップ プロジェクトに設定 を選択します。
F5 キーを押して、プログラムをデバッグ モードで実行します。
コード一覧
このサンプルは、CDSWebAPIService プロジェクトに含まれているアセンブリに依存しています。 このクラスが提供するメソッドについては、Web API CDSWebApiService クラス サンプル (C#) を参照してください。
以下は、Program.cs ファイルのコードです。
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Threading.Tasks;
namespace PowerApps.Samples
{
internal class Program
{
//Get configuration data from App.config connectionStrings
private static readonly string connectionString = ConfigurationManager.ConnectionStrings["Connect"].ConnectionString;
private static readonly ServiceConfig serviceConfig = new ServiceConfig(connectionString);
//Controls the max degree of parallelism
private static readonly int maxDegreeOfParallelism = 10;
//How many records to create with this sample.
private static readonly int numberOfRecords = 100;
private static void Main()
{
#region Optimize Connection
//Change max connections from .NET to a remote service default: 2
System.Net.ServicePointManager.DefaultConnectionLimit = 65000;
//Bump up the min threads reserved for this app to ramp connections faster - minWorkerThreads defaults to 4, minIOCP defaults to 4
System.Threading.ThreadPool.SetMinThreads(100, 100);
//Turn off the Expect 100 to continue message - 'true' will cause the caller to wait until it round-trip confirms a connection to the server
System.Net.ServicePointManager.Expect100Continue = false;
//Can decreas overall transmission overhead but can cause delay in data packet arrival
System.Net.ServicePointManager.UseNagleAlgorithm = false;
#endregion Optimize Connection
var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
var count = 0;
//Will be populated with account records to import
List<JObject> accountsToImport = new List<JObject>();
//ConcurrentBag is a thread-safe, unordered collection of objects.
ConcurrentBag<Uri> accountsToDelete = new ConcurrentBag<Uri>();
Console.WriteLine($"Preparing to create {numberOfRecords} acccount records using Web API.");
//Add account records to the list to import
while (count < numberOfRecords)
{
var account = new JObject
{
["name"] = $"Account {count}"
};
accountsToImport.Add(account);
count++;
}
try
{
using (CDSWebApiService svc = new CDSWebApiService(serviceConfig))
{
Console.WriteLine($"Creating {accountsToImport.Count} accounts");
var startCreate = DateTime.Now;
//Create the accounts in parallel
Parallel.ForEach(accountsToImport, parallelOptions, (account) =>
{
//Add the Uri returned to the ConcurrentBag to delete later
accountsToDelete.Add(svc.PostCreate("accounts", account));
});
//Calculate the duration to complete
var secondsToCreate = (DateTime.Now - startCreate).TotalSeconds;
Console.WriteLine($"Created {accountsToImport.Count} accounts in {Math.Round(secondsToCreate)} seconds.");
Console.WriteLine($"Deleting {accountsToDelete.Count} accounts");
var startDelete = DateTime.Now;
//Delete the accounts in parallel
Parallel.ForEach(accountsToDelete, parallelOptions, (uri) =>
{
svc.Delete(uri);
});
//Calculate the duration to complete
var secondsToDelete = (DateTime.Now - startDelete).TotalSeconds;
Console.WriteLine($"Deleted {accountsToDelete.Count} accounts in {Math.Round(secondsToDelete)} seconds.");
Console.WriteLine("Sample completed. Press any key to exit.");
Console.ReadLine();
}
}
catch (Exception)
{
throw;
}
}
}
}
関連項目
Dataverse Web API を使用する
Web API CDSWebApiService クラス サンプル (C#)
Web API CDSWebApiService の非同期並列操作のサンプル (C#)
Web API CDSWebApiService の基本操作のサンプル (C#)
Web API を使用してテーブル行を作成する
Web API を使用したテーブル行の更新と削除
注意
ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)
この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。
フィードバック
フィードバックの送信と表示