accountテーブルのtelephone1に登録後、関連するcontactのtelephone1に値を非同期でコピーする場合の手順は以下の通りです。
クラスファイルはプロジェクト内に2つあっても問題ありません。
1つのAssembly(dllファイル)に2つのPluginが出来上がる形になります。
クラスファイルの中身以外は以前の手順踏襲となります。
-
クラスファイルの編集
クラス名を変更し、開発を行います。using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; using Microsoft.Xrm.Sdk; using System.Text.RegularExpressions; using Microsoft.Xrm.Sdk.Query; namespace MyDataversePluginVS462 { public class FollowupPlugin3 : IPlugin { public void Execute(IServiceProvider serviceProvider) { // プラグイン実行コンテキストの取得 IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext)) as IPluginExecutionContext; if (context == null) { throw new InvalidPluginExecutionException("プラグイン実行コンテキストが取得できませんでした。"); } // 組織サービスファクトリの取得 IOrganizationServiceFactory serviceFactory = serviceProvider.GetService(typeof(IOrganizationServiceFactory)) as IOrganizationServiceFactory; if (serviceFactory == null) { throw new InvalidOperationException("IOrganizationServiceFactory が取得できませんでした。"); } // 組織サービスの取得(データ操作用) IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); // トレーシングサービスの取得 ITracingService tracingService = serviceProvider.GetService(typeof(ITracingService)) as ITracingService; if (tracingService == null) { throw new InvalidPluginExecutionException("トレーシングサービスが取得できませんでした。"); } // PostOperationの場合、InputParametersにTargetは存在しないため、OutputParameterから取得する。 // ①Createの場合、context.Outputparameters["id"]に作成したレコードのGUIDが含まれている。 // ②Updateの場合、context.InputParameters["Target"]に更新したレコードが含まれているが、 // PostOperationでは、更新後のデータが必要となるため、通常は取得したレコードを再度、サービスで取得し直す。 // ③Deleteの場合、context.InputParameters["Target"]に削除したレコードが含まれている。 // 今回はCreateとUpdateを利用します。 Entity account = null; if (context.MessageName == "Create" && context.OutputParameters.Contains("id")) { // 作成したレコードのGUIDを取得 Guid accountId = (Guid)context.OutputParameters["id"]; tracingService.Trace($"Account created with GUID:{accountId}"); // 作成したAccountを再取得 account = service.Retrieve("account", accountId, new ColumnSet("telephone1", "primarycontactid")); } else if (context.MessageName == "Update" && context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { // 更新したレコードを取得 // ※InputParametersのTargetは更新項目のみしか含まないため、再取得 Entity updateAccount = (Entity)context.InputParameters["Target"]; tracingService.Trace($"Account update with GUID:{updateAccount.Id}"); account = service.Retrieve("account", updateAccount.Id, new ColumnSet("telephone1", "primarycontactid")); } if (account == null) { tracingService.Trace("Account entity not found in context. Exiting plugin."); return; } // Accountの電話番号が空でないかチェック if (account.Contains("telephone1") && !string.IsNullOrWhiteSpace(account.GetAttributeValue<string>("telephone1"))) { string accountPhoneNumber = account.GetAttributeValue<string>("telephone1"); tracingService.Trace($"Account Phone Number: {accountPhoneNumber}"); // Primary Contanct(主取引先担当者)が設定されているかチェック if (account.Contains("primarycontactid") && account.GetAttributeValue<EntityReference>("primarycontactid") != null) { EntityReference primaryContactRef = account.GetAttributeValue<EntityReference>("primarycontactid"); tracingService.Trace($"Primary Contanct GUID: {primaryContactRef.Id}"); try { // ContactレコードをRetrieveして、電話番号が既に設定されているかチェック Entity contact = service.Retrieve("contact", primaryContactRef.Id, new ColumnSet("telephone1")); // Contactの電話番号が空欄の場合、または、Accountの電話番号と異なる場合、更新 if (!contact.Contains("telephone1") || contact.GetAttributeValue<string>("telephone1") != accountPhoneNumber) { Entity contactToUpdate = new Entity("contact", primaryContactRef.Id); contactToUpdate["telephone1"] = accountPhoneNumber; service.Update(contactToUpdate); tracingService.Trace($"Successfully updated Primary Cntact {primaryContactRef.Name} phone number to: {accountPhoneNumber}"); } else { tracingService.Trace($"Primary Contact phone number is alredy set or matches Account's. No update needed."); } } catch (Exception ex) { tracingService.Trace($"Error updating Primary Cotact phone number: {ex.Message}"); // 本番環境では、InvalidPluginExecutionExceptionをスローしてロールバックするのが良い。 //throw new InvalidPluginExecutionException("An error occurred during phone number synchronization.", ex); } } else { tracingService.Trace("No Primary Contact associated with this Account."); } } else { tracingService.Trace("Account does not have a telephone number or its's empty."); } // 処理全体をtry-catchで囲って、catchでInvalidPluginExecutionExceptionするのもあり。 } } }