1

まず、APIを介してセールスフォースとの間でデータを同期する製品があります。プラットフォームでレコードが更新されると、データはセールスフォースにプッシュされ、セールスフォースでデータが更新されると、製品にプッシュされます。私たちが直面している問題は、かなり厄介な無限ループです。誰がトリガーを実行しているかをSalesForceに判断して、製品のデータが更新されてSalesforceにプッシュされたときに、トリガーが起動しないようにする方法はありますか?これについての実行情報はこれまで見たことがないので、よくわかりません。

ありがとう!

4

5 に答える 5

4

Trigger.isExecuting以外に何かがあるとは思いません。これは、既にトリガーコンテキストにいるのか、Visualforce、APIから来ているのか、匿名で実行しているのかを示すだけです。

考えられる解決策の1つは、最新の更新の元を保持するカスタムフィールドを作成することです。これを使用して、トリガー内のロジックを適切にルーティングし、最後の更新が外部システムからのものであるときに呼び出されないようにすることができます。さらに、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;
                  }
            }
      }
}
于 2012-07-20T21:20:14.843 に答える
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
}

静的変数であるため、コードの実行中は設定されたままなので、apexが最初に設定するのはRecursive.setWorking();、残りのメソッド全体でトリガーが起動しないようにすることです。

于 2012-11-27T16:52:40.077 に答える
0

製品からのAPI呼び出しに専用ユーザーを使用している場合は、それらの送信メッセージの送信ユーザー権限を無効にすることができます。これにより、一部のトリガーコードの実行が停止することはありませんが、開発のたびに更新サイクルが妨げられます。

于 2012-07-29T06:44:04.547 に答える
0

同期を実行するタイミングをより適切に識別する方法について、Adamに同意します。UserInfo.getUserId()メソッドを使用して現在レコードを更新しているユーザーを調べてから、ユーザーを調べることも検討してください。

統合が機能するためには、ユーザーを外部製品に割り当てる必要があったと思います。うまくいけば、それは彼らに固有のアカウントであり、ベストプラクティスになるでしょう。もしそうなら、あなたは現在のユーザーが誰であるかを見ることができ、それがその外部製品であるならば、あなたは別のアップデートを送り返す試みを無視することができます。

于 2012-07-20T21:48:20.867 に答える
0

ロジックを除外する「免除ソース」ごとに、タイプNumber(18,0)のターゲットオブジェクトにフィールドを作成します。私は通常、このフィールドを「[ジョブ]による最終更新」のようなものと呼びます。このフィールドは、ユーザー向けのページレイアウトには配置しないでください。

次に、免除ソースが更新を実行するたびに、そのフィールドをSystem.currentTimeMillis()に設定します。トリガーは、そのフィールドが変更されているかどうかを確認し、変更されている場合は、そのソースで省略したいロジックを除外します。

Adamが言及した解決策(最新の更新のソースを保持する)も機能しますが、常に適切に更新したり、変更されたかどうかを確認したりしないと、エラーが発生しやすくなる可能性があります。そのため、ロジックの免除が必要なときに変更されるフィールドを好み、それらの免除された変更ソースに対してのみ更新する必要があります。

于 2012-07-23T00:55:19.107 に答える