SharePoint工作流程:如何在不触发工作流程的情况下更新项目

问题描述:

我有一个SharePoint工作流程只要项目发生变化就会运行。该工作流程与外部REST服务进行通信。如果服务返回一个字符串,我想用该字符串更新字段值之一。不幸的是,一旦当前工作流程终止,此更新将触发该项目的另一个工作流程实例。 我结束了一个无限循环!SharePoint工作流程:如何在不触发工作流程的情况下更新项目

我该如何防止这种情况发生? SPListItem具有Update(),UpdateOverwriteVersion()和SystemUpdate()方法,但它们都不妨碍后续工作流的触发。

我可以检查项目的上次修改时间戳,并在上次更新发生在特定时间范围内时终止工作流,但我正在寻找更强大的解决方案。

你可以使用一些扩展方法来默默更新项目列表项。

public static class SPListItemExtensions 
{ 
/// <summary> 
/// Provides ability to update list item without firing event receiver. 
/// </summary> 
/// <param name="item"></param> 
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param> 
public static void Update(this SPListItem item, bool doNotFireEvents) 
{ 
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling(); 
    if (doNotFireEvents) 
    { 
     try 
     { 
      rh.DisableEventFiring(); 
      item.Update(); 
     } 
     finally 
     { 
      rh.EnableEventFiring(); 
     } 
    } 
    else 
    { 
     item.Update(); 
    } 
} 

/// <summary> 
/// Provides ability to update list item without firing event receiver. 
/// </summary> 
/// <param name="item"></param> 
/// <param name="incrementListItemVersion"></param> 
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param> 
public static void SystemUpdate(this SPListItem item, bool incrementListItemVersion, bool doNotFireEvents) 
{ 
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling(); 
    if (doNotFireEvents) 
    { 
     try 
     { 
      rh.DisableEventFiring(); 
      item.SystemUpdate(incrementListItemVersion); 
     } 
     finally 
     { 
      rh.EnableEventFiring(); 
     } 
    } 
    else 
    { 
     item.SystemUpdate(incrementListItemVersion); 
    } 
} 

/// <summary> 
/// Provides ability to update list item without firing event receiver. 
/// </summary> 
/// <param name="item"></param> 
/// <param name="doNotFireEvents">Disables firing event receiver while updating item.</param> 
public static void SystemUpdate(this SPListItem item, bool doNotFireEvents) 
{ 
    SPItemEventReceiverHandling rh = new SPItemEventReceiverHandling(); 
    if (doNotFireEvents) 
    { 
     try 
     { 
      rh.DisableEventFiring(); 
      item.SystemUpdate(); 
     } 
     finally 
     { 
      rh.EnableEventFiring(); 
     } 
    } 
    else 
    { 
     item.SystemUpdate(); 
    } 
} 

private class SPItemEventReceiverHandling : SPItemEventReceiver 
{ 
    public SPItemEventReceiverHandling() { } 

    new public void DisableEventFiring() 
    { 
     base.DisableEventFiring(); 
    } 

    new public void EnableEventFiring() 
    { 
     base.EnableEventFiring(); 
    } 


    } 
} 
+0

这很好 - thx! – 2010-03-18 13:21:50

+1

建议:使用“using”模式实现SPItemEventReceiverHandling,请参阅http://adrianhenke.wordpress.com/2010/01/29/disable-item-events-firing-during-item-update/ – driAn 2010-05-07 08:35:23

+1

有关更多信息,请参阅下面的答案。适用于SP2010的示例和代码 – 2011-06-28 17:04:59

如果更新是由对该字段的更改触发的,那么您是否可以向终止工作流程的工作流程的开始添加一个步骤? (通过使用该服务进行更新的那个)。

当您使用服务更新列表时,您可以在列表项上设置一个隐藏布尔字段,该列表项中设置为true。然后,在工作流程开始时,您可以检查该字段是否设置为true。

+0

如何检测哪个字段发生了变化?我没有看到任何属性表明这一点。 – 2010-03-17 23:50:37

+0

对不起,我应该澄清我的意思。我更新了我的答案。 – UnhipGlint 2010-03-17 23:51:07

+0

但是,我不必再次取消设置该隐藏的布尔型字段(这将再次触发更新)? – 2010-03-17 23:59:58

您可以使用设置字段在当前项目 instud 更新列表项目

集字段更新了新的触发事件

+0

你能解释一下你的意思吗? – devi 2013-03-27 17:50:54

看来微软在SharePoint 2010中重写了这一点,EventFiringEnabled和EventFiringDisabled已经过时。

改为使用名为EventFiringEnabled的布尔型属性。

+0

感谢您提供链接并对已接受的答案发表评论。 – jumbo 2012-01-24 12:27:54