次の方法で共有


CreateMultiple と UpdateMultiple のプラグインを書き込む

CreateMultipleメッセージとUpdateMultiple メッセージが展開されています。 CreateUpdateをサポートするすべてのテーブルは、最終的にCreateMultipleUpdateMultipleをサポートしますが、一部のテーブルではまだサポートされていない場合があります。 一括操作メッセージの詳細

レコードを一括で作成または更新する必要があるテーブル、または多数のレコードの作成と更新のパフォーマンスが重要な場合に、 CreateMultiple および UpdateMultiple メッセージのプラグインを記述する必要があります。 ビジネス データを格納するすべてのテーブルを一括で作成または更新する必要がある場合があります。

このようなテーブルの CreateUpdate メッセージの既存のプラグインがある場合は、代わりに CreateMultipleUpdateMultiple を使用するように移行する必要があります。

プラグインの更新は必要ですか?

CreateMultipleUpdateMultipleではなく、CreateUpdateを使用するためにプラグインを移行する必要はありません。 アプリケーションが CreateMultiple または UpdateMultipleを使用する場合、ロジックは引き続き適用されます。 Dataverse メッセージ処理パイプラインは、これらのメッセージの単一バージョンまたは複数バージョンに対して記述された プラグインのロジックをマージ するため、プラグインを移行する必要はありません。

ただし、これらのメッセージの複数のバージョン用に記述されたプラグインのみがパフォーマンスを大幅に向上させます。 時間が経つにつれて、 CreateMultipleUpdateMultiple メッセージを使用してパフォーマンスを最適化することを選択する開発者が増えるにつれて、複数の操作のプラグインを記述することが標準になることを期待しています。 1 つの操作用に記述されたプラグインは例外です。

違いは何ですか?

プラグインを CreateMultiple メッセージと UpdateMultiple メッセージに移行するときに管理する必要がある相違点を次に示します。

ターゲットではなくターゲット

これらのメッセージの複数のバージョンには、単一のTarget ではなく、EntityCollection であるTargetsがあります。 プラグイン コードでは、コレクション内のエンティティをループ処理し、それぞれにロジックを適用する必要があります。

エンティティ イメージ

プラグインのステップ登録で構成されているエンティティ イメージは、 EntityImageCollection の配列です。 これらのエンティティ イメージは、PreEntityImagesCollection プロパティと PostEntityImagesCollection プロパティを提供する IPluginExecutionContext4 インターフェイスを使用する場合にのみ使用できます。 これらの配列は、EntityCollection と同期されている配列内の同じエンティティ イメージへのアクセスを提供します。

Power Platform ツールを使用してプラグイン プロジェクトを初期化するときに標準である PluginBase クラスを使用している場合は、 PluginBase.cs ファイルで、 IPluginExecutionContext のすべてのインスタンスを IPluginExecutionContext4 に置き換えて、これらのエンティティ イメージのコレクションをプラグインで使用できるようにする必要があります。

Important

CreateMultipleのプラグイン手順用にUpdateMultipleする場合は、含める列データを慎重に選択することが重要です。 すべての列の既定のオプションを選択しないでください。 このデータには、 Targets パラメーターで渡されたエンティティの数が乗算され、サンドボックスに送信されるメッセージの合計サイズに寄与します。 メッセージ サイズの制限に達する可能性があります。

属性フィルター

UpdateまたはUpdateMultipleに登録されているプラグインの場合は、ステップ登録でフィルター属性を指定できます。

  • Updateでは、選択した属性のいずれかが更新中のTarget エンティティに含まれている場合にのみ、プラグインが実行されます。
  • UpdateMultipleでは、選択した属性のいずれかが パラメーターのいずれかのエンティティTargets含まれている場合にプラグインが実行されます。

Important

UpdateMultipleでは、Targets パラメーター内のすべてのエンティティに、フィルターで使用される属性が含まれているとは想定できません。

Example

次の例では、 Update の基本的なロジックと、 UpdateMultipleのロジックを使用して、ステップに登録されたエンティティ イメージにアクセスします。

次の使用例は、sample_description値が変更されたかどうかに関する情報を使用して、sample_name属性を更新します。 これは、ステップに登録された example_preimage という名前のエンティティ イメージを参照します。

// Verify input parameters
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity entity)
{

   // Verify expected entity image from step registration
   if (context.PreEntityImages.TryGetValue("example_preimage", out Entity preImage))
   {

      bool entityContainsSampleName = entity.Contains("sample_name");
      bool entityImageContainsSampleName = preImage.Contains("sample_name");
      bool entityImageContainsSampleDescription = preImage.Contains("sample_description");

      if (entityContainsSampleName && entityImageContainsSampleName && entityImageContainsSampleDescription)
      {
            // Verify that the entity 'sample_name' values are different
            if (entity["sample_name"] != preImage["sample_name"])
            {
               string newName = (string)entity["sample_name"];
               string oldName = (string)preImage["sample_name"];
               string message = $"\\r\\n - 'sample_name' changed from '{oldName}' to '{newName}'.";

               // If the 'sample_description' is included in the update, do not overwrite it, just append to it.
               if (entity.Contains("sample_description"))
               {

                  entity["sample_description"] = entity["sample_description"] += message;

               }
               else // The sample description is not included in the update, overwrite with current value + addition.
               {
                  entity["sample_description"] = preImage["sample_description"] += message;
               }

               // Success:
               localPluginContext.Trace($"Appended to 'sample_description': \"{message}\" ");
            }
            else
            {
               localPluginContext.Trace($"Expected entity and preImage 'sample_name' values to be different. Both are {entity["sample_name"]}");
            }
      }
      else
      {
            if (!entityContainsSampleName)
               localPluginContext.Trace("Expected entity sample_name attribute not found.");
            if (!entityImageContainsSampleName)
               localPluginContext.Trace("Expected preImage entity sample_name attribute not found.");
            if (!entityImageContainsSampleDescription)
               localPluginContext.Trace("Expected preImage entity sample_description attribute not found.");
      }
   }
   else
   {
      localPluginContext.Trace($"Expected PreEntityImage: 'example_preimage' not found.");
   }
}
else
{
   if (!context.InputParameters.Contains("Target"))
      localPluginContext.Trace($"Expected InputParameter: 'Target' not found.");
   if (!(context.InputParameters["Target"] is Entity))
      localPluginContext.Trace($"Expected InputParameter: 'Target' is not Entity.");
}

例外の処理

プラグインで発生するすべてのエラーは 、InvalidPluginExecutionException を使用して返す必要があります。 プラグインが CreateMultiple に登録された手順と UpdateMultiple メッセージの例外をスローする場合、プラグインが失敗した原因となったレコードを特定する必要があります。 この情報をキャプチャするには、次のいずれかのコンストラクターを使用します。

これらのコンストラクターを使用すると、 InvalidPluginExecutionException.ExceptionDetails プロパティに値を追加できます。これは直接設定することはできません。

コンストラクターの Dictionary<String,String>exceptionDetails パラメーターを使用して、失敗したレコードとその他の関連情報に関する情報を含めます。

例外の詳細を設定する

UpdateMultiple メッセージの場合、コードは EntityCollectionTargets プロパティを反復処理し、各エンティティにロジックを適用します。 エラーが発生した場合は、次の方法でレコードの ID をInvalidPluginExecutionExceptionコンストラクターに渡すことができます。

// in plugin code
foreach (Entity entity in Targets)
{
   // [...] When an error occurs:
   var exceptionDetails = new Dictionary<string, string>();
   exceptionDetails.Add("failedRecordId", (string)entity.Id);
   throw new InvalidPluginExecutionException("This is an error message.", exceptionDetails);
}

エラーに関連するその他の情報を文字列キーと値のペアとして exceptionDetails パラメーターに追加します。

CreateMultipleの場合は、各レコードの主キー値を設定しないことをお勧めします。 ほとんどの場合、システムによって生成される値は最適なパフォーマンスを得るために最適化されているため、システムに主キー値の設定を許可する必要があります。

主キー値が設定されていない場合、他の一意の識別子がない場合は、 EntityCollectionTargets パラメーターで失敗したレコードのインデックス、または失敗したレコードを一意に識別する値の組み合わせを返す必要があります。 たとえば、failedRecordIndex内のレコードの位置を示すEntityCollectionという名前のキーや、その他の便利な一意識別子をexceptionDetailsに追加して、エラーのトラブルシューティングに役立てることができます。

例外の詳細を取得する

InvalidPluginExecutionException.ExceptionDetails プロパティに失敗した操作の詳細を含めると、クライアント アプリケーションは、FaultExceptionOrganizationServiceFault.Detail プロパティを介してOrganizationServiceFault.ErrorDetails プロパティからそれらを取得できます。 次のコードは、その方法を示しています。


try
{
   // xMultiple request that triggers your plugin
}
catch (FaultException<OrganizationServiceFault> ex)
{
   ex.Detail.ErrorDetails.TryGetValue("failedRecordId", out object failedRecordId);
}

クライアント アプリケーションが Web API を使用している場合は、要求ヘッダーを設定することでPrefer: odata.include-annotations="*"できます。

ソリューション内の単一操作プラグインを置き換える

ソリューションにプラグイン ステップの登録を展開する場合、ステップ登録を強制的に無効にしたり削除したりすることはできません。 これにより、ロジックを 1 つの操作から複数の操作プラグインに置き換える作業が困難になります。

CreateMultipleまたはUpdateMultipleのプラグイン ステップを置き換えるCreateまたはUpdateのソリューションに新しいプラグイン ステップをデプロイする場合は、ロジックまたは重複するロジックが適用されない時間を短縮する必要があります。 ソリューションのインストール前またはインストール後に、 Create または Update の手順を手動で無効にすることができます。 以前に無効にした場合、ロジックが適用されない期間があります。 後で無効にすると、重複するロジックが適用される期間があります。 どちらの場合も、組織では、ロジックが一貫して適用されるように、スケジュールされたダウンタイムが必要になる場合があります。

これらのいずれかの条件の期間を最小限に抑えるために、新しいプラグインを パッケージ 配置ツールで展開することによって置き換えられるステップを無効にするロジックを含めるのが推奨されます。 Package Deployer には、パッケージが環境にインポートされる前、実行中、および後に カスタム コード を実行する機能が用意されています。 このコードを使用して、既存のステップの登録を無効にします。

こちらも参照ください

サンプル: CreateMultiple および UpdateMultiple プラグイン
一括操作メッセージ
サンプル: .NET 用 SDK 一括操作の使用
一括操作で最適化されたパフォーマンス