3

削除トリガーの前に Apex ジョブを実行していますが、Salesforce インターフェースを介して単一のキャンペーンを削除するのに約 34 秒かかり、キャンペーンが削除されると Apex ジョブの実行が完了していることに気付きました。VisualForce ページを使用して同じ数のレコード (15,000) で同じ Apex ジョブを実行すると、Apex ジョブはキューに入れられ、VisualForce ページが完了した後に実行されます。

このスクリーン ショットでは、最初のジョブは VisualForce を使用してキューに入れられ、2 番目と 3 番目のジョブはトリガーを使用してキューに入れられました。

頂点の仕事

ご覧のとおり、トリガーを使用してキューに入れられたときに同じ Apex ジョブによって同じ数のレコード (15,000) が処理されますが、バッチは作成されず、送信日と完了日はまったく異なります。

Apex ジョブはトリガーでキューに入れられます:

trigger DeleteChilds on Campaign (before delete) {
public static final Integer MAX_DELETED = 500;
Set<ID> ids = new Set<Id>();
List<Parent__c> objs = new List<Parent__c>();   

for(Campaign c : Trigger.old)
    ids.add(c.Id);

objs = [SELECT Id FROM Parent__c WHERE Campaign__c IN :ids];

ids = new Set<Id>();

for(Parent__c s : objs)
    ids.add(s.Id);

Integer childCount = [SELECT count() FROM Childs__c WHERE Parent__c IN :ids];

if(childCount < MAX_DELETED){
    List<Childs__c> childs = [SELECT Id FROM Childs__c WHERE Parent__c IN :ids];

    delete childs;  
} else {                 
    String deleteQuery = 'SELECT Id FROM Childs__c WHERE ';

    for(ID id : ids){
        deleteQuery += String.format(' Parent__c = \'\'{0}\'\' OR', new String[] {id});
    }   

    if(deleteQuery.endsWith('OR')){
        deleteQuery = deleteQuery.substring(0, deleteQuery.length() - 2);
    }               

    BatchDeleteChilds batch = new BatchDeleteChilds();
    batch.deleteQuery = deleteQuery;

    ID batchId = Database.executeBatch(batch);      
}

delete objs;
}

これは Apex ジョブです。

global class BatchDeleteChilds implements Database.Batchable<sObject> {
public String deleteQuery;

global Database.QueryLocator start(Database.BatchableContext context){
    return Database.getQueryLocator(deleteQuery);
}

global void execute(Database.BatchableContext context, List<sObject> records){
    delete records;
    DataBase.emptyRecycleBin(records);
}   

global void finish(Database.BatchableContext context){

}   
}

他の誰かがこのようなことを経験しましたか?

ありがとう、

4

1 に答える 1

2

おそらく決して勝てない競合状態を見ています。削除された親オブジェクトは、データベース内の子から親へのルックアップを無効にするバッチ ジョブが実行されるまでにコミットされます。このため、バッチに渡すクエリにはレコードがありません。

  • 子の事前削除: (name = 'example', parent__c = '123')
  • 削除後 (バッチ前) 子: (name = 'example', parent__c = null)

このアプローチの動機となった設計上の決定はわかりませんが、子レコードを一括削除するために利用できる他のオプションがあります。最も簡単な方法は、子から親への関係をマスター詳細にすることです。このタイプの関係では、子レコードは自動的に削除されます。

次に、親オブジェクトの削除ボタンを Visualforce ページでオーバーライドできます。次に、コントローラーは子をカウントし、バッチ プロセスを起動してそれらを削除するかどうかを決定します。次に、終了メソッドになるまで、バッチ プロセスで親オブジェクトの削除を待機させます。

于 2012-07-04T00:37:15.223 に答える