Dataverse插件创建更新流程:选Pre还是Post操作?
插件注册:Post操作 vs Pre操作的选择分析
你的场景是在Order实体创建/更新时,根据文本字段abs_requestid匹配对应的Request记录,填充abs_request lookup字段。当前Post操作插件能正常运行,但从性能和逻辑合理性来说,强烈建议改用Pre操作,原因如下:
当前Post操作的问题
- 额外触发一次
Update请求:你的代码在Post阶段单独调用service.Update(entityUpdate),等于对同一个Order记录发起两次数据库操作(原始的Create/Update + 这次额外的Update),增加了系统开销。 - 可能触发额外插件:如果有其他插件注册在Order的
Update消息上,这次额外的Update会再次触发这些插件,容易引发不必要的逻辑执行甚至循环触发风险。 - 逻辑冗余:Post阶段是在记录已经保存到数据库后再修改,完全可以在保存前完成字段填充,避免多此一举。
Pre操作的优势
在Pre操作中,你可以直接修改InputParameters里的Target实体,把abs_request lookup字段添加进去,平台会自动将这个字段包含在原始的Create/Update请求中,一次数据库操作完成所有字段的保存,性能更优,逻辑更简洁。
修改后的Pre操作插件代码
public class UpdateOrderPlugIN : IPlugin { public void Execute(IServiceProvider serviceProvider) { ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); try { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity targetEntity) { if (targetEntity.Attributes.Contains("abs_requestid")) { tracingService.Trace("Pre操作:填充Request lookup字段"); PopulateRequestLookup(tracingService, service, targetEntity); } } } catch (FaultException<OrganizationServiceFault> e) { throw new InvalidPluginExecutionException("UpdateOrderPlugIN执行出错", e); } catch (Exception e) { tracingService.Trace($"PopulateRequestLookup异常:{e.ToString()}"); throw; } } private static void PopulateRequestLookup(ITracingService tracingService, IOrganizationService service, Entity orderEntity) { tracingService.Trace("开始填充Request lookup"); string requestId = orderEntity.GetAttributeValue<string>("abs_requestid"); tracingService.Trace($"Request ID:{requestId}"); // 根据Request ID获取对应的实体引用 var requestRef = new EntityReference("abs_request", "abs_requestid", requestId); // 直接将lookup字段添加到Target实体,平台会自动保存 orderEntity["abs_request"] = requestRef; tracingService.Trace("Request lookup字段填充完成"); } }
注意事项
- 确保
abs_requestid是abs_request实体的唯一标识字段(比如设置为唯一约束),否则EntityReference的这个构造方法可能返回错误的记录。 - 注册插件时,选择对应的消息(Create/Update),并将执行阶段设置为PreValidation或PreOperation(推荐PreOperation,字段值已经经过验证)。
内容的提问来源于stack exchange,提问作者tlas956
相关产品推荐
相关产品推荐

