0

我正在为我的自定义实体 (OpportunityService) 开发一个更新插件。我的目标是比较更新前后的数据。这就是我为 Pre image 和 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 值的地方获取它们。当其中任何一个为空时,将不会将属性添加到机会服务对象中,并且在尝试检索它时会出现异常。

于 2013-08-31T19:01:47.100 回答
0

我知道这是一篇旧文章,但是要将实体(例如从 PreEntityImages、PostEntityImages 和 InputParameters 获得的实体)转换为像“机会”这样的强类型类,请使用扩展方法:

.ToEntity<opportunity>()
于 2014-02-28T15:41:02.013 回答
0

使用 context.InputParameters["Target"] 你得到一个实体。此实体仅包含已更改的属性。

于 2013-09-01T10:00:26.450 回答
0
  Entity postOpportunityService = (Entity)context.PostEntityImages["OpportunityService"];

对于 CRM 中的后期绑定数据模型,如果 CRM 中的“OpportunityService”字段没有实际值,上述语句将抛出“Key not found”错误。所以这基本上意味着该领域没有任何东西。

您可以手动检查您尝试获取的每个属性是否为空,或者您可以只使用crmsvcutil并自动生成您的 CRM 模型。这将为您提供一个强类型模型,并且您不必再担心属性的空值检查。

于 2013-08-31T19:08:24.753 回答