CRM插件的执行导致无限循环

时间:2018-07-11 17:24:48

标签: c# plugins dynamics-crm

我有一个名为项目分配的自定义实体,并且在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);
   }
}

1 个答案:

答案 0 :(得分:2)

看来您已经实现了这一点:

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

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,则该字段也会被更新(为相同的值)。您可能想避免这种情况,可以通过创建一个新的实体对象来实现。