2012-07-20 112 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