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

Dynamics 365销售订单明细插件报错0x80040265求助

销售订单明细插件创建时锁定错误排查与解决建议

问题现象

开发的插件在**销售订单明细(salesorderdetail)**实体创建事件触发时,出现实体锁定错误,插件跟踪日志如下:

get Ref
productIdRef
de_prdrate: 19
de_salesprdrate: 19

System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: The product and the unit cannot be updated while the entity is locked. (Fault Detail is equal to Exception details:
ErrorCode: 0x80040265
Message: The product and the unit cannot be updated while the entity is locked.
OriginalException: PluginExecution ExceptionSource: PluginExecution

补充信息:销售订单明细的创建事件同时有系统工作流在运行,该插件在**报价单明细(quotedetail)**实体上运行无异常,怀疑是插件与系统工作流触发同一事件导致冲突。

插件代码

public class Update_Salesdetails_Field : 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)
        {
            Entity entity = (Entity)context.InputParameters["Target"];
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            try
            {
                if (entity.LogicalName != "salesorderdetail")
                {
                    tracingService.Trace("Target entity is not Sales Order Detail! plug-in was not registered correctly! Exit PlugIn", serviceProvider);
                    throw new InvalidPluginExecutionException("The current entity is not the Sales Order Detail entity");
                }

                tracingService.Trace("get Ref", serviceProvider);
                var productIdRef = entity.GetAttributeValue<EntityReference>("productid");

                tracingService.Trace("productIdRef", serviceProvider);
                var productEntity = service.Retrieve("product", productIdRef.Id, new ColumnSet("de_prdrate"));

                tracingService.Trace("de_prdrate: " + productEntity["de_prdrate"]);
                entity["de_salesprdrate"] = productEntity["de_prdrate"];

                tracingService.Trace("de_salesprdrate " + entity["de_salesprdrate"]);
                service.Update(entity);

                tracingService.Trace("Update salesprdrate " + entity["de_salesprdrate"]);
            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                tracingService.Trace("exception:", ex.ToString());
                tracingService.Trace(ex.StackTrace);

                if (ex.InnerException != null)
                {
                    tracingService.Trace("inner exception:", ex.InnerException.ToString());
                    tracingService.Trace(ex.InnerException.StackTrace);
                }

                throw new InvalidPluginExecutionException(ex.Message);
            }
            catch (Exception ex)
            {
                tracingService.Trace("FollowUpPlugin: {0}", ex.ToString());
                tracingService.Trace(ex.StackTrace);
                throw;
            }
        }
    }
}

解决方案建议

1. 切换到Pre-Create阶段执行(最优方案)

当前插件应该是注册在**Post-Create(创建后)**阶段,此时调用service.Update会触发额外的更新请求,而系统工作流可能已经锁定了实体(尤其是涉及产品、单位字段的操作)。

将插件注册到**Pre-Create(创建前)**阶段,直接在Target实体上设置de_salesprdrate字段值即可,无需调用service.Update——Pre阶段对Target的修改会直接被包含在创建请求中,彻底避免实体锁定冲突。

修改后的核心逻辑:

// 移除原代码中的service.Update(entity);
// 直接赋值,Pre阶段自动带入创建操作
entity["de_salesprdrate"] = productEntity["de_prdrate"];
tracingService.Trace("Set de_salesprdrate to " + entity["de_salesprdrate"]);

2. 调整插件执行顺序

如果必须在Post-Create阶段执行,调整插件的执行顺序,让它在系统工作流之后运行。这样系统工作流完成字段处理并释放锁定后,插件再执行更新操作。

3. 添加重试逻辑处理短暂锁定

在更新操作外包裹重试逻辑,应对短暂的实体锁定情况:

int retryCount = 3;
while (retryCount > 0)
{
    try
    {
        service.Update(entity);
        break;
    }
    catch (FaultException<OrganizationServiceFault> ex) when (ex.Detail.ErrorCode == 0x80040265)
    {
        retryCount--;
        if (retryCount == 0) throw;
        System.Threading.Thread.Sleep(1000); // 等待1秒后重试
    }
}

4. 排查系统工作流的操作

查看系统工作流对销售订单明细的具体操作:

  • 确认是否有长时间锁定实体的逻辑
  • 检查工作流是否也修改了de_salesprdrate字段,导致冲突
  • 若存在字段操作冲突,可以将逻辑合并到插件或工作流中,避免重复操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:46:05