CRM 2011插件:实体图像:KeyNotFoundException

时间:2013-08-31 15:53:22

标签: dynamics-crm-2011 dynamics-crm

我正在为自定义实体(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()); }
        }
    }
}

我的插件同步在Post操作阶段(Update message)注册。

我在这里做错了,我看不到?

提前谢谢。

编辑:这是答案

谢谢你的回答。通过阅读它们并试图弄清楚什么是错的,我终于明白问题不在于实体图像,而在于这条线:

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

因为它是Update消息,它只返回“Target”的更改值,“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 个答案:

答案 0 :(得分:1)

你能确切地指出你得到这个例外的确切线路吗?

你可以在获得图像的地方获取它们,但也可以获得mpc_monthlyprice,mpc_startprice和mpc_estinvoicingperyear的值。如果其中任何一个为null,则不会将属性添加到opportunityService对象,并且在尝试检索它时会出现异常。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

使用context.InputParameters [“Target”]获得一个实体。该实体仅包含已更改的属性。

答案 3 :(得分:0)

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

.ToEntity<opportunity>()