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

能否实现无递归的同步Post Operation D365CE插件更新触发实体字段?

D365CE同步Post Operation插件递归问题求解

我是D365CE插件开发新手,当前遇到同步Post Operation插件更新实体字段时的递归问题。我知道代码中IOrganizationService的update操作会引发更新事件递归,但想确认是否可以实现一个同步运行、能获取记录Post Operation值并更新同实体其他字段且无递归的插件?我了解可以检查context.depth,但这种方式可能导致数据不一致,不被推荐。

插件注册信息

  • 消息:Update
  • 主实体:quote
  • 筛选属性:statecode
  • 管道:PostOperation
  • 执行模式:Synchronous

示例代码

public class Quote_SetEffectiveDates : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

        if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
        {
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(null);

            try
            {
                if (context.PrimaryEntityId != null)
                {
                    ColumnSet quote_Col = new ColumnSet("statecode");
                    Entity quote = service.Retrieve("quote", context.PrimaryEntityId, quote_Col);
                    int statecode = quote.GetAttributeValue<OptionSetValue>("statecode").Value;
                  
                    if (statecode  == 1)
                    {
                        DateTime currentDate = DateTime.UtcNow.Date;

                        Entity quote_Update = new Entity
                        {
                            LogicalName = quote.LogicalName,
                            Id = quote.Id,
                        };
                        quote_Update["effectivefrom"] = currentDate;
                        quote_Update["effectiveto"] = currentDate.AddDays(30);

                        service.Update(quote_Update);
                    }
                }
            }

            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw new InvalidPluginExecutionException("An error occured in Quote_SetEffectiveDates plugin", ex);
            }

            catch (Exception ex)
            {
                tracingService.Trace("Quote_SetEffectiveDates; {0}", ex.ToString());
                throw;
            }
        }
    }
}

已尝试方案

  • 注册在Pre Operation:无法获取Post Operation的记录值,不符合需求。
  • 异步运行插件:可解决递归问题,但我强烈希望使用同步模式。

解决方案

1. 利用筛选属性阻断递归

你当前的插件注册已设置筛选属性为statecode,这意味着只有当statecode字段被修改时,插件才会触发。你的代码中仅更新effectivefrom和effectiveto两个字段,这两个字段不在筛选列表内,因此执行service.Update(quote_Update)时不会再次触发该插件,天然避免递归。

如果仍出现递归,需检查插件注册是否正确配置筛选属性,确保没有误选其他字段。

2. 通过PostImage替代Retrieve提升性能

当前代码中使用service.Retrieve获取statecode,可以改为通过PostImage直接获取Post Operation后的最新值,无需额外查询,同时避免潜在的数据一致性问题:

  • 插件注册时,添加PostImage,勾选statecode字段;
  • 代码中从context.PostEntityImages读取数据:
// 替换原Retrieve逻辑
if (context.PostEntityImages.Contains("PostImage") && context.PostEntityImages["PostImage"] is Entity postQuote)
{
    int statecode = postQuote.GetAttributeValue<OptionSetValue>("statecode").Value;
    // 后续逻辑不变
}

3. 代码内添加触发条件判断(双重保险)

在代码开头增加判断,仅当Target实体包含statecode属性时才执行后续逻辑,确保插件仅在statecode被修改时运行:

Entity target = (Entity)context.InputParameters["Target"];
// 仅当statecode被修改时才执行
if (!target.Contains("statecode"))
{
    tracingService.Trace("Quote_SetEffectiveDates: statecode未被修改,跳过执行");
    return;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:16:21