Apex Job未在Trigger中异步运行

时间:2012-06-29 01:36:48

标签: salesforce

我在删除触发器之前运行Apex Job并发现通过Salesforce界面删除单个Campaign需要大约34秒,并且在删除Campaign时Apex Job已完成运行。当我使用VisualForce页面在相同数量的记录(15,000)上运行相同的Apex作业时,Apex Job排队并在VisualForce页面完成后运行。

在此屏幕截图中,第一个作业使用VisualForce排队,第二个和第三个作业使用触发器排队:

Apex Jobs

正如您所看到的,虽然相同的Apex作业在使用“触发器”排队时处理相同数量的记录(15,000),但不会创建任何批次,并且“提交”和“已完成”日期完全不同。

Apex Job在触发器中排队:

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){

}   
}

有没有其他人经历过这样的事情?

谢谢,

1 个答案:

答案 0 :(得分:2)

你正在寻找一个你可能永远不会赢的竞争条件。已删除的父对象将在批处理作业执行时提交,这会使数据库中从子节点到父节点的查找为空。因此,传递给批处理的查询将没有记录。

  • 预删除子项:(名称='示例',parent__c ='123')
  • 删除后(批量前)子项:(名称='示例',parent__c = null)

我不知道推动此方法的设计决策,但还有其他选项可用于批量删除子记录。最简单的方法是让孩子与父母的关系成为主要细节。使用此类关系会自动删除子记录。

其次,您可以使用visualforce页面覆盖父对象的删除按钮。然后,控制器将对子项进行计数,并决定是否启动批处理以删除它们。然后让批处理等待删除父对象,直到它完成方法。