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

Dataverse插件创建更新流程:选Pre还是Post操作?

插件注册:Post操作 vs Pre操作的选择分析

你的场景是在Order实体创建/更新时,根据文本字段abs_requestid匹配对应的Request记录,填充abs_request lookup字段。当前Post操作插件能正常运行,但从性能和逻辑合理性来说,强烈建议改用Pre操作,原因如下:

当前Post操作的问题

  1. 额外触发一次Update请求:你的代码在Post阶段单独调用service.Update(entityUpdate),等于对同一个Order记录发起两次数据库操作(原始的Create/Update + 这次额外的Update),增加了系统开销。
  2. 可能触发额外插件:如果有其他插件注册在Order的Update消息上,这次额外的Update会再次触发这些插件,容易引发不必要的逻辑执行甚至循环触发风险。
  3. 逻辑冗余: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:12:51