You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dynamics 365插件创建关联实体记录报字典键不存在错误求解

问题场景

涉及两个Dataverse实体:

  • MemberTransaction:会员交易主表
  • MemberTransactionDetail:会员交易明细表
    业务要求:新建MemberTransaction记录时,自动同步创建一条关联的MemberTransactionDetail记录。

实体字段定义

MemberTransaction 字段

MemberTransactionId PK,
MemberTransactionNo String,
TransactionDate DateTime,
MemberId LookUp

MemberTransactionDetail 字段

MemberTransactionDetailId PK,
MemberTransactionId LookUp,
ProductId LookUp,
Qty number

原有实现代码

public void Execute(IServiceProvider serviceProvider)
    {
        try
        {
            var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            var postImage = context.PostEntityImages["PostImage"];
            var entity = (Entity)context.InputParameters["Target"];

            if (entity.Attributes.Contains("KEY"))
            {
                var memberTransactionId = postImage.GetAttributeValue<Guid>("trn_membertransactionid");
                var memberTransactionNo = postImage.GetAttributeValue<String>("trn_membertransactionno");

                var transactionDetail = new Entity("trn_membertransactiondetail");
                transactionDetail["trn_membertransactionno"] = memberTransactionNo;
                transactionDetail["trn_membertransactionid"] = new EntityReference("trn_membertransactiondetail", memberTransactionId);
                transactionDetail["trn_transactiondetailno"] = "6667";

                var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                var service = serviceFactory.CreateOrganizationService(context.UserId);
                var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

                tracingService.Trace("Plugin: Creating the Transaction Detail.");
                service.Create(transactionDetail);

                var transactionDetailId = transactionDetail.Id;
                tracingService.Trace("The Detail Id is " + transactionDetailId);
            }
        }
        catch (Exception ex)
        {
            Console.Write("What?" + ex.Message);
        }
    }

报错信息

插件运行时抛出异常:The given key was not present in the dictionary.

排查与修复方案

该错误是字典键值匹配失败导致,按以下优先级定位修复即可:

  1. PostImage 注册缺失/别名不匹配(最高概率诱因)
    代码在进入逻辑判断前就执行了context.PostEntityImages["PostImage"]取值,只要插件步骤没有注册别名严格为PostImage的Post-operation实体镜像,这行代码会直接抛出键不存在错误。
    修复方式:
    • 打开插件注册工具,找到绑定MemberTransaction实体Create消息的插件步骤
    • 注册后期镜像,别名设为PostImage,将代码用到的trn_membertransactionid、trn_membertransactionno字段加入镜像字段列表
    • 更简单的方案:Create消息触发时,InputParameters里的Target实体本身就携带新建记录的主键ID,完全不需要依赖PostImage,直接用entity.Id就能获取主记录ID,可省去镜像注册步骤。
  2. 无效硬编码判断导致逻辑不执行
    代码中if (entity.Attributes.Contains("KEY"))是无效判断,KEY是无意义硬编码字符串,主实体属性集合中不可能存在该键,即使PostImage配置正确,内部创建明细的逻辑块也永远不会执行。
    修复方式:直接删除该无效判断,或替换为实际需要的业务校验逻辑(比如判断必填字段不为空)。
  3. 查找字段EntityReference配置错误
    给明细表关联主表的查找字段赋值时,new EntityReference("trn_membertransactiondetail", memberTransactionId)的实体名写反,指向了明细表自身而非主表,即使前面逻辑正常,执行Create操作时也会触发关联字段校验错误。
    修复方式:将实体名修正为主表逻辑名:
    transactionDetail["trn_membertransactionid"] = new EntityReference("trn_membertransaction", memberTransactionId);
    
  4. 异常捕获逻辑失效
    现有catch块用Console.Write输出错误完全无效,插件运行无控制台上下文,异常会被吞掉无法定位具体出错行。
    修复方式:用追踪服务记录完整错误栈,再将异常抛给平台展示:
    catch (Exception ex)
    {
        tracingService.Trace("Plugin error: {0}", ex.ToString());
        throw new InvalidPluginExecutionException("自动创建交易明细失败", ex);
    }
    

额外注意:插件步骤需要注册在Post-operation阶段、同步执行模式,避免主记录未完成持久化时创建明细导致关联失败。

修正后核心可运行代码

public void Execute(IServiceProvider serviceProvider)
{
    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    var service = serviceFactory.CreateOrganizationService(context.UserId);
    var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
    try
    {
        Entity target = (Entity)context.InputParameters["Target"];
        // 直接从Target取新建主记录的ID,无需PostImage
        Guid mainRecordId = target.Id;
        string transactionNo = target.GetAttributeValue<string>("trn_membertransactionno");

        Entity detail = new Entity("trn_membertransactiondetail");
        // 关联主记录,注意实体名不要写错
        detail["trn_membertransactionid"] = new EntityReference("trn_membertransaction", mainRecordId);
        // 明细表存在对应字段再赋值,否则删除该行
        // detail["trn_membertransactionno"] = transactionNo;
        detail["trn_transactiondetailno"] = "6667";

        tracingService.Trace("Start creating transaction detail for main record: " + mainRecordId);
        Guid detailId = service.Create(detail);
        tracingService.Trace("Transaction detail created, ID: " + detailId);
    }
    catch (Exception ex)
    {
        tracingService.Trace("Full error stack: " + ex.ToString());
        throw new InvalidPluginExecutionException("交易明细创建失败:" + ex.Message, ex);
    }
}

内容的提问来源于stack exchange,提问作者Haminteu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:48:46