一括操作メッセージを使う
Microsoft Dataverse テーブルの複数行に対して操作を実行する際に最高のパフォーマンスを得るには、次の一括操作メッセージを使用します:
CreateMultiple
: 1 つのリクエストで同じタイプの複数のレコードを作成します。UpdateMultiple
: 1 つのリクエストで同じタイプの複数のレコードを更新します。UpsertMultiple
: 1 つのリクエストで同じタイプの複数のレコードを作成して更新します。DeleteMultiple
(プレビュー): エラスティック テーブルのみ。 1 つのリクエストで同じタイプの複数のレコードを削除します。
注意
ExecuteMultiple
などのバッチ API と比較してこれらの API を使用する場合など、一括操作を実行するときのオプションに関するガイダンスについては、一括操作で最適化されたパフォーマンス を参照してください。
使用例
次のサンプル コードは、一括操作メッセージの使用方法を示しています。 サンプルをここからダウンロードできます github.com/microsoft/PowerApps-Samples:
CreateMultiple
1 つのリクエストで同じタイプの複数のレコードを作成します。
CreateMultipleRequest クラスを使用します。
/// <summary>
/// Demonstrates the use of the CreateMultiple Message
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="recordsToCreate">A list of records of the same table to create.</param>
/// <returns>The Guid values of the records created.</returns>
static Guid[] CreateMultipleExample(IOrganizationService service,
List<Entity> recordsToCreate)
{
// Create an EntityCollection populated with the list of entities.
EntityCollection entities = new(recordsToCreate)
{
// All the records must be for the same table.
EntityName = recordsToCreate[0].LogicalName
};
// Instantiate CreateMultipleRequest
CreateMultipleRequest createMultipleRequest = new()
{
Targets = entities,
};
// Send the request
CreateMultipleResponse createMultipleResponse =
(CreateMultipleResponse)service.Execute(createMultipleRequest);
// Return the Ids of the records created.
return createMultipleResponse.Ids;
}
UpdateMultiple
1 つのリクエストで同じタイプの複数のレコードを更新します。
個々のレコードを更新する場合と同様に、UpdateMultiple
で送信するデータは、変更する値のみを含める必要があります。 .NET 用 SDK を使用してレコードを更新する方法と Web API を使用してレコードを更新する方法について説明します。
UpdateMultipleRequest クラスを使用します。
/// <summary>
/// Demonstrates the use of the UpdateMultiple message.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="recordsToUpdate">A list of records to create.</param>
static void UpdateMultipleExample(IOrganizationService service, List<Entity> recordsToUpdate) {
// Create an EntityCollection populated with the list of entities.
EntityCollection entities = new(recordsToUpdate)
{
// All the records must be for the same table.
EntityName = recordsToUpdate[0].LogicalName
};
// Use UpdateMultipleRequest
UpdateMultipleRequest updateMultipleRequest = new()
{
Targets = entities,
};
service.Execute(updateMultipleRequest);
}
UpdateMultiple Targets パラメータの重複レコード
ペイロード内の同じ主キーまたは 代替キー 値を持つ複数のレコードは、 UpdateMultiple
でサポートされていません。 複数のレコードがある場合、Targets
パラメータがプライマリまたは代替キーによって一意に識別される場合、操作は最初のレコードに対してのみ実行されます。 ペイロード内の同じキー値を持つ後続のレコードは無視されます。 この動向は UpsertMultiple
とは異なります。
UpsertMultiple
このテーブルが Dataverse に存在するかどうかが不明な場合は、Upsert
を使用してデータを外部ソースと統合します。 Upsert
操作はレコードを識別する際に、代替キーに依存します。 UpsertMultiple
を使用して Upsert
操作を一括で実行します。
UpsertMultipleRequest クラスを使用します。
この静的 UpsertMultipleExample
メソッドは、代替キーとして構成された samples_accountname
という名前の文字列の列を持つ、samples_bankaccount
テーブルに依存します。 これには、samples_description
という名前の文字列の列もあります。 このコードは代替キー値の指定に keyName と keyValue を設定するエンティティ コンストラクター を使用します。
/// <summary>
/// Demonstrates using UpsertMultiple with alternate key values
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance</param>
static void UpsertMultipleExample(IOrganizationService service)
{
var tableLogicalName = "samples_bankaccount";
// samples_accountname string column is configued as an alternate key
// for the samples_bankaccount table
var altKeyColumnLogicalName = "samples_accountname";
// Create one record to update with upsert
service.Create(new Entity(tableLogicalName)
{
Attributes =
{
{altKeyColumnLogicalName, "Record For Update"},
{"samples_description","A record to update using Upsert" }
}
});
// Using the Entity constructor to specify alternate key
Entity toUpdate = new(
entityName: tableLogicalName,
keyName: altKeyColumnLogicalName,
// Same alternate key value as created record.
keyValue: "Record For Update");
toUpdate["samples_description"] = "Updated using Upsert";
Entity toCreate = new(
entityName: tableLogicalName,
keyName: altKeyColumnLogicalName,
keyValue: "Record For Create");
toCreate["samples_description"] = "A record to create using Upsert";
// Add the records to a collection
EntityCollection records = new()
{
EntityName = tableLogicalName,
Entities = { toUpdate, toCreate }
};
// Send the request
UpsertMultipleRequest request = new()
{
Targets = records
};
var response = (UpsertMultipleResponse)service.Execute(request);
// Process the responses:
foreach (UpsertResponse item in response.Results)
{
Console.WriteLine($"Record {(item.RecordCreated ? "Created" : "Updated")}");
}
}
出力:
Record Updated
Record Created
この例でレコードが作成されるか更新されるかは、sample_keyattribute
の値が一致するレコードが存在するかどうかによって決まります。 データ レコードが作成済み、更新済み、または削除済みのどれであるかを示します
SDK の例
空き時間
UpsertMultiple
は CreateMultiple
と UpdateMultiple
に対応したテーブルで使用できます。 これには、すべてのエラスティック テーブルが含まれます。 標準テーブルの可用性 にあるクエリは、UpsertMultiple
の結果を返しませんが、テーブルが CreateMultiple
と UpdateMultiple
の両方をサポートしているかどうかを検出するために使用できます。
これらのクエリは UpsertMultiple
メッセージの結果を返しません。 CreateMultiple
と UpdateMultiple
の両方をサポートするテーブルが UpsertMultiple
をサポートします。
UpsertMultiple Targets パラメータの重複レコード
ペイロード内の同じ主キーまたは 代替キー 値を持つ複数のレコードは、 UpsertMultiple
でサポートされていません。 Targets
パラメータ内の複数のレコードがプライマリまたは 代替キー によって一意に識別される場合、UpsertMultiple
はエラーを返します。 この動向は UpdateMultiple
とは異なります。
標準テーブルとエラスティック テーブルの使用法
これらの一括操作メッセージを使用すると、標準テーブルとエラスティック テーブルの両方でパフォーマンスが大幅に向上しますが、使い分けが必要です。 次の表では、違いについて要約します。
差分 | Standard | エラスティック |
---|---|---|
レコードの数 | レコード数が多いほど、操作は効率的になります。 レコードの数に制限はありませんが、メッセージのサイズと時間には制限があります。 一度に 100~1000 件のレコードを送信することをお勧めします。 | 一度に 100 件のレコードを送信することをお勧めします。 |
エラー時の動作 | エラーが発生すると、すべての操作がロールバックされます。 | 部分的に成功する可能性はあります。 |
可用性 | すべての標準テーブルがこれらのメッセージをサポートしているわけではありません。 | メッセージはすべてのエラスティック テーブルで利用可能です。 |
DeleteMultiple | 使用不可。 代わりに、SDK BulkDeleteRequest クラス または Web API BulkDelete アクション を使用します。 データを一括削除する方法をご覧ください。 | SDK OrganizationRequest クラスを使用することで利用可能です。 Web API DeleteMultiple アクションは非公開ですが、現在は使用できます。 すぐに公開される予定です。 |
標準テーブルとエラスティック テーブルの使用方法は異なりますが、これは標準テーブルが Azure SQL を使用し、トランザクションをサポートしているためです。 エラスティック テーブルは Azure Cosmos DB を使用しますが、これはトランザクションをサポートしないものの、低遅延で高レベルのスループットで大量のデータを処理できます。 以下のセクションで詳細情報を説明します。 エラスティック テーブルでの一括操作の詳細をご覧ください。
レコードの数
各リクエストに含める必要があるレコードの数は、標準テーブルを使用しているか、エラスティック テーブルを使用しているかによって異なります。
ヒント
一括操作メッセージを並行して送信すると、標準テーブルとエラスティック テーブルの両方でスループットが向上します。
標準テーブルのレコード件数
標準テーブルでの一括操作は、単一トランザクションで複数の行に対して実行するように最適化されています。 リクエストあたりの操作数が増加すると、操作がより効率的になり、全体的なパフォーマンスが向上します。 この最適化により、一括操作用に登録された任意のプラグイン ステップの効率も向上します。 単一の操作でプラグインが呼び出されるたびに、ロジックを含むプラグイン クラスを呼び出すのに数ミリ秒かかります。 プラグインが一括操作メッセージに登録されると、クラスが 1 回呼び出され、すべての操作をより効率的に処理できます。 CreateMultiple および UpdateMultiple (プレビュー) のプラグインを記述する方法について説明します。
このパフォーマンス上の利点により、各リクエストでできる限り多くのレコードを送信するインセンティブが得られます。 ただし、レコードの数が増えると、リクエストのサイズも大きくなり、リクエストの処理に時間がかかるようになります。 最終的には、メッセージのサイズと時間制限が発生します。 これらの制限に達すると、操作全体が失敗します。 送信できるレコード数に制限はありません。 最適な数値を見つけるには、実験が必要になるかもしれません。 一般に、レコード データのサイズが小さく、プラグインがない場合は、リクエストあたり 100~1,000 レコードから始めるのが妥当であると予想されます。発生する可能性のある種類のエラーは、通常、各リクエストで送信するレコードの数を減らすことで対処できます。 送信するエンティティの数を構成する機能を含めて、送信するエンティティの数を減らして調整できるようにすることをお勧めします。
エラスティック テーブルのレコード件数
エラスティック テーブルにはトランザクションがないため、リクエストごとにレコードの最大数を送信しようとしてもパフォーマンス上の利点はありません。 最大のスループットを実現するには、リクエストごとに 100 の操作を送信し、リクエストを並行して送信することをお勧めします。
エラー時の動作
エラーが発生したときの動作は、標準テーブルとエラスティック テーブルのどちらを使用しているかによって異なります。
標準テーブルでのエラー時の動作
標準テーブルを使用した一括操作でエラーが発生すると、操作全体がロールバックされます。 すべての操作が成功するという確信度が高い場のみ、標準テーブルで一括操作を使用する必要があります。 SDK ExecuteMultipleRequest クラスまたは Web API $batch
を使用して、一括操作が失敗する場合に一連の操作がフォールバックするように使用することもできます。 最初の試行の成功率が低い場合、この戦略ではパフォーマンスが低下します。 このフォールバック戦略は、ほとんどの操作が成功すると予想される場合にのみ使用してください。
エラスティック テーブルでのエラー時の動作
エラスティック テーブルでは、一括操作が部分的に成功する場合があります。 エラーの詳細を使用して、失敗したレコードを特定できます。
SDK でエラスティック テーブルで一括操作を実行すると、障害が発生した場合に OrganizationServiceFault タイプの FaultException がスローされます。 次のコードを使用して、各レコードのステータスを取得できます。
if (ex.Detail.ErrorDetails.TryGetValue("Plugin.BulkApiErrorDetails", out object errorDetails))
{
List<BulkApiErrorDetail> bulkApiErrorDetails = JsonConvert.DeserializeObject<List<BulkApiErrorDetail>>(errorDetails.ToString());
}
public class BulkApiErrorDetail
{
public int RequestIndex { get; set; }
public string Id { get; set; }
public int StatusCode { get; set; }
}
空き時間
一括操作メッセージを利用できるかどうかは、標準テーブルとエラスティック テーブルのどちらを使用しているかによって異なります。 すべてのエラスティック テーブルは CreateMultiple
、UpdateMultiple
、UpsertMultiple
、および DeleteMultiple
メッセージをサポートしています。
参照 :
標準テーブルでの可用性
CreateMultiple
および UpdateMultiple
一括操作メッセージは、カスタム標準テーブルや多くの共通標準テーブルに対して使用できますが、すべてではありません。 個々の標準テーブルがこれらのメッセージをサポートしているかどうかをテストする必要があります。 次の例は、テストする方法を示しています。
この静的メソッドを使用して、特定のテーブルが CreateMultiple
または UpdateMultiple
をサポートしているかどうかを検出します。
/// <summary>
/// Detect whether a specified message is supported for the specified table.
/// </summary>
/// <param name="service">The IOrganizationService instance.</param>
/// <param name="entityLogicalName">The logical name of the table.</param>
/// <param name="messageName">The name of the message.</param>
/// <returns></returns>
public static bool IsMessageAvailable(
IOrganizationService service,
string entityLogicalName,
string messageName)
{
QueryExpression query = new("sdkmessagefilter")
{
ColumnSet = new ColumnSet("sdkmessagefilterid"),
Criteria = new FilterExpression(LogicalOperator.And)
{
Conditions = {
new ConditionExpression(
attributeName:"primaryobjecttypecode",
conditionOperator: ConditionOperator.Equal,
value: entityLogicalName)
}
},
LinkEntities = {
new LinkEntity(
linkFromEntityName:"sdkmessagefilter",
linkToEntityName:"sdkmessage",
linkFromAttributeName:"sdkmessageid",
linkToAttributeName:"sdkmessageid",
joinOperator: JoinOperator.Inner)
{
LinkCriteria = new FilterExpression(LogicalOperator.And){
Conditions = {
new ConditionExpression(
attributeName:"name",
conditionOperator: ConditionOperator.Equal,
value: messageName)
}
}
}
}
};
EntityCollection entityCollection = service.RetrieveMultiple(query);
return entityCollection.Entities.Count.Equals(1);
}
メッセージ パイプラインの統合
各一括操作メッセージには、Create
、Update
、Delete
という、個々の行の操作に対応するメッセージがあります。 これらのメッセージは長い間存在しており、多くの組織がこれらのメッセージの使用時に発生するイベントに応じてロジックをカスタマイズしています。
一括操作メッセージの重要な要件は、組織がカスタム ロジックを 2 つの場所で保守する必要がないことです。 同じカスタム ロジックを持ち、それを一箇所で維持するために、これらのメッセージのメッセージ処理パイプラインを統合しました。 具体的な変更点
一括操作メッセージが使用されると、
Targets
パラメーターの各エンティティ インスタンスに対してそれぞれCreate
とUpdate
イベントが発生します。 対応する個々のイベントの任意プラグインまたはその他のイベント ハンドラーは、これまでと同様に引き続き機能します。 これらのメッセージによって発生するイベントを管理するために新しいプラグインを作成する必要はありません。単一操作メッセージが使用されると、
Targets
パラメーターに渡される単一エンティティ インスタンスを含む EntityCollectionにそれぞれ一括操作イベントが発生します。 現在単一操作イベントに応答しているロジックをより効率的な一括操作イベントに移動でき、そのロジックは個々の操作と複数操作の両方に適用されます。
一括操作メッセージが導入される前は、すべてのカスタム ロジックは単一の操作メッセージ上にありました。 クライアント アプリケーションが一括操作メッセージを使用する場合は、そのロジックを引き続き適用する必要があります。 大量の一括操作で使用されるテーブルについては、任意の同期ロジックを単一メッセージ イベントから一括操作イベントに移行し始めることをお勧めします。 新しいロジックを導入する場合は、単一操作イベントではなく一括操作イベントを使用してください。
注意事項
この設計では、重複ロジックがイベントの単一バージョンと複数バージョンの両方に適用される可能性があります。 意図が分からないため、Dataverseはこれを防ごうとはしません。
イベントの単一バージョンに適用される同じロジックが、イベントの複数バージョンに移行され、イベントの単一バージョンから削除されるよう確認してください。 それ以外の場合、ロジックは 2 回適用されます。
CreateMultiple および UpdateMultiple (プレビュー) のプラグインを記述する方法について説明します。
制限
一括操作メッセージを使用する場合は、次の制限事項に留意してください。
メッセージのサイズと時間制限
標準テーブルでは、各リクエストでより多くのレコードを送信するというパフォーマンス上のインセンティブがあります。 ただし、送信できるレコードの数は、ペイロードのサイズと操作の処理に必要な時間によって制限されます。
メッセージ サイズの制限
メッセージにプラグインを登録している場合、リクエストの合計サイズが 116.85 MBを超えると、"サンドボックスにコンテキストを送信する際のメッセージ サイズを超えました" のエラーが発生する場合があります。 一括操作メッセージの場合、より大きなペイロードを送信すると、この制限に達する可能性が高くなります。
イベントにプラグインが登録されていない場合、このエラーは発生しません。 エラーを回避するには、プラグインを無効にするか、リクエストを BypassCustomPluginExecution
オプションのパラメーターで送信します。
時間の制限
Dataverse ServiceClient を使用している場合、このようなエラーが発生する場合があります:
The request channel timed out attempting to send after 00:04:00.
Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding.
The time allotted to this operation may have been a portion of a longer timeout.
ServiceClient で設定される既定のタイムアウトは 4 分で、これは同期操作としては長時間と見なされます。 この値は静的メソッド ServiceClient.MaxConnectionTimeout プロパティを使用して変更できます。 CrmServiceClient を使用したタイムアウトの既定値は 2 分です。
注意
時間制限を増やす前に、Targets
パラメータで渡されたレコード件数の減少を検討する必要があります。
プラグインでの使用はサポートされていない
現時点では、プラグイン コードでの一括操作メッセージの使用はサポートされていません。 詳細: プラグインとワークフロー活動でバッチ要求タイプを使用しないでください。
ただし、CreateMultiple と UpdateMultiple のプラグイン で説明されているように、CreateMultiple
および UpdateMultiple
のメッセージ用のプラグインを作成する 必要があります。
一般的なエラーのトラブルシューティング
一括操作の使用中にエラーが発生した場合は、次の記事を参照してください。
よくあるご質問 (FAQ)
この記事で一括操作メッセージの使用に関する質問への回答が見つからい場合は、このページの下部にあるボタンを使用して、このページに対するフィードバックを送信して表示します。 フィードバックを送信するには、GitHub アカウントが必要です。
Retrieve ロジックと RetrieveMultiple ロジックはマージされますか?
Retrieve
および RetrieveMultiple
メッセージ動作を変更する予定はありません。 これらは長年別々のメッセージであり、開発者は常にそれらのロジックを個別に維持する必要がありました。 これらのメッセージ パイプラインを統合しようとすることは、大きな問題です。 また、パフォーマンスに影響を与える可能性があるため、これらのメッセージにカスタム ロジックを適用することはお勧めできません。
API の制限はどのように適用されますか?
API 制限事項には次の 2 つの種類があります。 一括操作メッセージでは、どのタイプを回避する方法も提供されません。
サービス保護の制限
サービス保護 API の制限 で説明されているように、制限には 3 つの側面があります。 これらの制限のうち 2 つは、5 分間のスライディング ウィンドウで評価され、これらのメッセージを使用するときに適用されます。
- リクエスト数: 各一括操作メッセージは 1 つのリクエストとしてカウントされ、五分間のウィンドウ内でユーザーごと、サーバーごとに 6,000 リクエスト件の上限まで累積します。 これらのリクエストは個々の操作をグループ化するため、この制限に達する可能性は低くなります。
- 実行時間: 通常、各一括操作メッセージのリクエストには時間がかかるため、リクエストを並行して送信している場合は、五分間の時間枠内で、ユーザーごと、サーバーごとに 20 分という実行時間制限に達する可能性が高くなります。
Power Platform 要求 (API 権利) の制限
これらの制限はデータの変更に基づいています: Create
、 Update
、Delete
操作。 一括操作リクエストの Targets
パラメータに含まれる各項目は、この制限まで加算されます。 要求の制限と割り当てに関する詳細。
参照
UpsertMultiple の使用 (プレビュー)
DeleteMultiple の使用 (プレビュー)
エラスティック テーブル
CreateMultiple と UpdateMultiple のプラグインを書き込む
サンプル: .NET 用 SDK 一括操作の使用
サンプル: Web API 一括操作の使用
サンプル: CreateMultiple および UpdateMultiple プラグイン
.NET 用 SDK でメッセージを使用する
一括操作で最適化されたパフォーマンス