【问题标题】:CRM Plugin execution causing an infinite loopCRM 插件执行导致无限循环
【发布时间】:2018-07-11 17:24:48
【问题描述】:

我有一个名为项目分配的自定义实体,我在 LastUpdatedOn 字段的更新后触发了一个插件。

插件更新同一实体上的可用数量字段,没有其他字段。

我不明白为什么它会导致无限循环。我收到以下错误:

此工作流作业已取消,因为启动它的工作流包含无限循环。

任何帮助将不胜感激。这是我的代码。

Entity entItemAllocation = (Entity)context.InputParameters["Target"];

if (context.PostEntityImages.Contains("PostImage") && context.PostEntityImages["PostImage"] is Entity)
{
   //get PostImageEntity
   Entity postImageEntity = context.PostEntityImages["PostImage"];

   int qtyAvailable = 0;
   if (postImageEntity.Attributes.Contains("wo_lotnumber"))
      lotNum =  postImageEntity.Attributes["wo_lotnumber"].ToString();
   if (postImageEntity.Attributes.Contains("wo_itemnumber"))
      itemNum = ((EntityReference)postImageEntity.Attributes["wo_itemnumber"]).Id;

   if (postImageEntity.Attributes.Contains("wo_qtyavailable"))
      qtyAvailable = Convert.ToInt32(postImageEntity.Attributes["wo_qtyavailable"]);

   if (dictAssignLotQty.ContainsKey($"{lotNum}|{itemNum}"))
   {
      decimal assignLotQty = dictAssignLotQty[$"{lotNum}|{itemNum}"];
      qtyAvailable -= Convert.ToInt32(assignLotQty);

      entItemAllocation["wo_qtyavailable"] = qtyAvailable;
      service.Update(entItemAllocation);
   }
}

【问题讨论】:

    标签: c# plugins dynamics-crm


    【解决方案1】:

    看起来你已经实现了这个:

    1. 更新entItemAllocation
    2. entItemAllocation 上更新wo_qtyavailable

    CRM 将识别第 2 步发生的更新,并在第 1 步重新启动您的插件,这种模式将不断重复。你现在有一个无限循环。作为保障,CRM 最终会停止循环插件。

    就避免这种情况的方法而言:

    1. 在代码中添加一些逻辑检查,例如如果 wo_qtyavailable 已经是正确的值,请不要更新它。

    2. 使用depth 检查。

    平台用于防止无限循环。

    每次运行插件或工作流向 触发另一个插件或工作流执行的 Web 服务, 执行上下文的 Depth 属性增加了。如果深度 属性在配置的时间内增加到最大值 限制,平台将此行为视为无限循环,并且 进一步的插件或工作流执行被中止。

    //At the start of your plugin
    //If depth is greater than 1 skip rest of plugin logic.
    //In some scenarios you might need to use 2, 3, etc, you will have to work that out based on how many events are executing in CRM before your plugin is called.
    if (context.Depth > 1) { return; }
    
    //Rest of plugin logic
    ...
    
    1. Use attribute filtering on your plugin registration,这限制了将触发插件执行的字段数。

    2. Run your plugin on pre-update,然后您可以在 Target 上设置字段,这些字段将进入 CRM,而无需单独拨打 service.Update 电话。

    作为旁注;

    Entity entItemAllocation = (Entity)context.InputParameters["Target"];
    ...
    entItemAllocation["wo_qtyavailable"] = qtyAvailable;
    ...
    service.Update(entItemAllocation);
    

    这会将entItemAllocation 中已包含的任何字段发送到 CRM,例如如果Target 包含wo_name,该字段也将被更新(相同的值)。你可能想避免这种情况,你可以通过创建一个新的实体对象来做到这一点。

    【讨论】:

    • 将执行从 PostOperation 更改为 PreOperation 解决了这个问题,因为不需要使用 Preoperation 在目标实体上显式调用更新方法。
    猜你喜欢
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2017-12-24
    • 2020-08-27
    • 2021-05-07
    相关资源
    最近更新 更多