2012-07-20 60 views
1

首先,我们有一款产品可以通过api将数据与salesforce进行同步和从salesforce进行同步。当我们的平台正在更新记录时,数据会被推送到salesforce,当数据在salesforce中更新时,会将其推送到我们的产品。我们遇到的问题是一个相当麻烦的无限循环。在SalesForce中有没有办法确定谁在执行触发器,以便在我们的产品中更新数据并推送到salesforce时,触发器不会触发?我之前没有看到关于这个的执行信息,所以我真的不确定它。Salesforce触发器无限循环

谢谢!

回答

4

我不相信Trigger.isExecuting以外的任何东西,它只是告诉你,你是否已经在触发器上下文中,或者你是来自Visualforce,API还是匿名执行。

一个可能的解决方案是创建一个自定义字段,保留最近更新的来源。这可以用来在触发器内正确路由逻辑,并避免在最后一次更新来自外部系统时调出。此外,您可以遍历Trigger.old和trigger.new中的所有字段,以查看哪些字段已更改。这样就能避免更多不必要同步到外部系统的时候没有什么有趣的关于你的记录(SystemTimeStamp,LastModifiedDate等)实际上改变了这里是如何做到这一点的例子:

trigger ContactDescribeExample on Contact (before update) 
{ 
     // Get describe fields to evaluate old and new triggers with 
     Map<String, Schema.SObjectField> fldObjMap = Schema.SObjectType.Contact.fields.getMap(); 
     List<Schema.SObjectField> fldObjMapValues = fldObjMap.values(); 

     // Flag to determine if field(s) other than FirstName caused this change (FirstName is just an example) 
     Boolean hasOtherChange = false; 

     // Loop through trigger batch 
     for(Contact c : Trigger.new) 
     { 
      for(Schema.SObjectField s : fldObjMapValues) 
      { 
        String fldName = s.getDescribe().getName(); 

        // Filter out fields we're not interested in 
        if(fldName != 'FirstName' && fldName != 'LastModifiedDate' && fldName != 'LastModifiedById' && fldName != 'SystemModstamp') 
        { 
         // Check to see if old and new are different 
         if(c.get(fldName) != Trigger.oldMap.get(c.Id).get(fldName)) 
           hasOtherChange = true; 
        } 
      } 
     } 
} 
+0

太棒了,这当然有帮助,我认为一定会解决这个问题。我很欣赏迅速的回复! – jsfdev01 2012-07-20 21:44:14

+0

没问题。很高兴帮助。 – Adam 2012-07-21 00:55:46

0

我与亚当商定如何以更好地识别何时执行同步。您也可以考虑使用UserInfo.getUserId()方法查看当前正在更新记录的用户,然后查找用户。

我想为了让您的集成工作,您必须将用户分配给外部产品。希望这是一个独一无二的帐户,这将是最佳做法。如果是这样,那么你可以看看当前用户是谁,如果是外部产品,你可以忽略尝试发送另一个更新。

0

对于您希望过滤出逻辑的每个“豁免源”,可在Number(18,0)类型的目标对象上创建一个字段。我通常把这个字段称为“最后更新者[Job]”。该字段不应该放在任何面向用户的页面布局上。

然后,只要您的豁免源执行更新,就将该字段设置为System.currentTimeMillis()。您的触发器会检查该字段是否已更改,如果已经更改,则免除您希望为该来源忽略的逻辑。

Adam提到的解决方案 - 保留最新更新的源代码 - 也可以工作,但如果您并不总是正确地更新它或检查它是否发生了更改,我发现它可能会出错。这就是为什么我更喜欢在您想要逻辑豁免时更改的字段,您只需更新它以获取免除更改的来源。

0

如果您正在使用专用用户接收来自您的产品的API调用,那么您可以为他们禁用Send Outbound Messages用户权限。这不会阻止一些触发器代码的运行,但它会阻止每一次开发的更新周期。

1

对于在Google上发现此问题的人,我通过添加一个设置触发器然后检查的公共静态变量的类来解决非常类似的问题。它默认为false,如果设置为true,则触发器不运行。下面的例子:

public class Recursive { 
    // Static variables to avoid recursion on trigger operation 

    private static boolean working = false; 

    public static boolean isWorking() { 
     return working; 
    } 

    // Set variable to true to mark record as working 

    public static void setWorking() { 
     working = true; 
    } 

    public static void setClosed() { 
     working = false; 
    } 

} 

然后触发器被包裹在以下几点:

if (!Recursive.isWorking()) { 
    // trigger code here 
} 

作为一个静态变量,它保持设定整个代码执行,所以第一件事就是我的顶点集是Recursive.setWorking();防止在其余方法中触发。

+0

2个问题。 1 - 您何时/何时重置国旗? 2 - 如果其他人正在更新SF UI中的数据,该怎么办? – Moon 2013-02-16 01:53:22

+0

我不会在任何地方手动重置标志,因为它只会在调用它的类/触发器的范围内持续存在。如果其他人正在更新相同的数据,他们的触发器实例将拥有自己的Recursive实例。 – 2013-11-26 17:36:09