0

カスタム エンティティ (OpportunityService) の更新プラグインを開発しています。私の目標は、更新の前後のデータを比較することです。そのため、Pre イメージと Post イメージ タイプの両方にエンティティ イメージを登録しました。イメージの名前は OpportunityService で、エイリアスも OpportunityService です。

次に、私のコードでは、いくつかのフィールドが変更されているかどうかを確認できるように、それらの画像を取得しようとしています。変更されている場合は、いくつかのアクションを実行します。しかし、それは私の質問の範囲ではありません。

次のようにエンティティ画像を参照しようとしています

Entity preOpportunityService = (Entity)context.PreEntityImages["OpportunityService"];
Entity postOpportunityService = (Entity)context.PostEntityImages["OpportunityService"];

しかし、その時点で私のプラグインは System.Collections.Generic.KeyNotFoundException をスローします。

「ビジネス プロセス エラー。プラグイン (実行) からの予期しない例外: OpportunityServicePlugin.OpportunityServiceCalculatorOnUpdate: System.Collections.Generic.KeyNotFoundException: 指定されたキーがディクショナリに存在しませんでした。」

現時点での私の完全なコードは次のように単純です。

using System;
using System.ServiceModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace OpportunityServicePlugin
{
    public class OpportunityServiceCalculatorOnUpdate: IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {

            // General plugin components 

            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            try
            {
                // Current opportunity service
                Entity opportunityService = (Entity)context.InputParameters["Target"];

                // Opportunity service's parent opportunity lookup reference
                EntityReference opportunityReference = (EntityReference)opportunityService.Attributes["mpc_opportunityid"];

                // Columns to be retrieved for opportunity (aka. columns to be edited)
                ColumnSet opportunityColumnSet = new ColumnSet(new string[] { "estimatedvalue", "mpc_estoneoffinvoicing", "mpc_estinvoicingperyear" });

                // Retrieve actual opportunity entity
                Entity opportunity = service.Retrieve(opportunityReference.LogicalName, opportunityReference.Id, opportunityColumnSet);

                // Opportunity service's money fields
                Money monthlyPrice = (Money)opportunityService["mpc_monthlyprice"];
                Money oneOffPrice = (Money)opportunityService["mpc_startprice"];
                Money estInvoicingPerYear = (Money)opportunityService["mpc_estinvoicingperyear"];

                Entity preOpportunityService = (Entity)context.PreEntityImages["OpportunityService"];
                Entity postOpportunityService = (Entity)context.PostEntityImages["OpportunityService"];

            }
            catch (FaultException<OrganizationServiceFault> ex) { tracingService.Trace("FaultException", ex.ToString()); }
        }
    }
}

私のプラグインは、ポスト操作段階 (更新メッセージ) で同期的に登録されます。

ここで何が間違っているのですか?

前もって感謝します。

編集:ここに答えがあります

回答ありがとうございます。それらを読んで何が悪いのかを理解しようとすることで、問題はエンティティ画像ではなく、次の行にあることが最終的にわかりました。

EntityReference opportunityReference = (EntityReference)opportunityService.Attributes["mpc_opportunityid"];

したがって、それは更新メッセージであり、「ターゲット」の変更された値のみを返すため、「mpc_opportunityid」が実際の問題でした-.-

コードを次のように変更しました

try
{
    Entity preOpportunityService = (Entity)context.PreEntityImages["OpportunityService"];
    Entity postOpportunityService = (Entity)context.PostEntityImages["OpportunityService"];

    // Opportunity service's parent opportunity lookup reference
    EntityReference opportunityReference = (EntityReference)postOpportunityService.Attributes["mpc_opportunityid"];

    // Columns to be retrieved for opportunity (aka. columns to be edited)
    ColumnSet opportunityColumnSet = new ColumnSet(new string[] { "estimatedvalue", "mpc_estoneoffinvoicing", "mpc_estinvoicingperyear" });

    // Retrieve actual opportunity entity
    Entity opportunity = service.Retrieve(opportunityReference.LogicalName, opportunityReference.Id, opportunityColumnSet);             

}
catch (FaultException<OrganizationServiceFault> ex) { tracingService.Trace("FaultException", ex.ToString()); }

そして今、それは動作します...

4

4 に答える 4

1

この例外が発生する行を正確に特定できますか?

画像を取得する場所で取得できますが、mpc_monthlyprice、mpc_startprice、および mpc_estinvoicingperyear の値を取得する場所でも取得できます。それらのいずれかが null の場合、属性は機会サービス オブジェクトに追加されず、取得しようとすると例外が発生します。

于 2013-08-31T19:01:47.100 に答える
0

これが古い投稿であることは承知していますが、PreEntityImages、PostEntityImages、および InputParameters から取得したようなエンティティを "opportunity" のような厳密に型指定されたクラスに変換するには、拡張メソッドを使用します。

.ToEntity<opportunity>()
于 2014-02-28T15:41:02.013 に答える
0
  Entity postOpportunityService = (Entity)context.PostEntityImages["OpportunityService"];

CRM のレイト バインド データ モデルでは、CRM の「OpportunityService」フィールドに実際の値がない場合、上記のステートメントは「キーが見つかりません」というエラーをスローします。したがって、これは基本的に、フィールドには何もないことを意味します。

null を取得しようとしている各プロパティを手動でチェックするか、crmsvcutilを使用して CRM モデルを自動的に生成することができます。これにより、厳密に型指定されたモデルが提供され、プロパティの null チェックについて心配する必要がなくなります。

于 2013-08-31T19:08:24.753 に答える