能否实现无递归的同步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
相关产品推荐
相关产品推荐

