帐户触发器更新所有联系人 - SOQL查询太多:101

时间:2014-04-09 04:58:52

标签: triggers salesforce apex soql

我有一个在更新任何帐户后运行的触发器,它实际上只是在几个条件后更新所有相关联系人中的字段(Relationship_category_r__c)。

条件1:如果我们将帐户类型更新为“会员” 条件2:如果联系人在(Relationship_category_r__c)字段中没有“成员” 操作:将联系人Relationship_Category_r__c字段更新为“会员 - 员工”

条件2:如果我们将帐户类型更新为“会员 - 过去” 操作:将所有联系人Relationship_Category_r__c字段更新为“成员 - 过去”

当帐户少于25到50个联系人时,触发器可以正常查找,但当我们拥有超过55个联系人的帐户时,它会生成错误

错误:Apex触发器UpdateAllContacts导致意外异常,请联系您的管理员:UpdateAllContacts:System.LimitException:SOQL查询太多:101

======================================= TRIGGER ======= =======================

trigger UpdateAllContacts on Account (after update) {
    for ( Account acc : Trigger.New ) {
        List<Contact> listCon = [Select id, Relationship_Category_r__c from Contact where AccountId =: acc.id];
        for ( Contact con : listCon ) {
            if ( acc.Type=='Member' ) {
                if ( con.Relationship_Category_r__c != 'Member' ) {
                    con.Relationship_Category_r__c = 'Member - staff';
                }
            } else if ( acc.Type=='Member - past ' ) {
                con.Relationship_Category_r__c = 'Member - past';
            }
        }
        try {
            update listCon;
        }
        catch (DmlException e) {}
    }
}

非常感谢任何帮助

由于

1 个答案:

答案 0 :(得分:1)

在这里突然发现了一些事情:

  • 首先是导致错误的主要原因:循环中的SOQL查询。您需要批量化触发器以执行单个查询,而不是为更新批次中的每个帐户记录查询一次。
  • 您在同一个循环中有一个DML操作(update listCon;),如果碰巧在您的Contact触发器中有任何SOQL查询,这将加剧问题。此更新也应该批量化,以便您尽可能少地插入/更新(在这种情况下,您可以将其限制为单个更新调用)。
  • 您正在更新所有查询的联系人记录,无论他们是否已通过您的代码更新。这可能会导致不必要的长处理时间,并且可以通过跟踪哪些记录应在第二个列表中更新来轻松防止。
  • 这可能是设计使然,但您可以在不尝试处理更新调用的情况下抑制更新调用中的任何错误。根据您的实现,有很多不同的方法可以解决这个问题,所以我不会深入研究,但在大多数情况下,您可能希望至少知道您对这些记录的更新失败,因此您可以更正问题。

在对您的代码进行一些更正之后,我们留下以下内容,它使用单个SOQL查询,单个DML语句,并且不会更新触发器尚未修改的任何联系人记录:

trigger UpdateAllContacts on Account (after update) {
    List<Contact> updateCons = new List<Contact>();
    for ( Contact con : [select Id, AccountId, Relationship_Category_r__c from Contact where AccountId in :Trigger.NewMap.keySet()] ) {
        Account parentAcc = Trigger.NewMap.get(con.AccountId);
        if ( parentAcc.Type == 'Member' ) {
            if ( con.Relationship_Category_r__c != 'Member' ) {
                con.Relationship_Category_r__c = 'Member - staff';
                updateCons.add(con);
            }
        } else if ( parentAcc.Type == 'Member - past ' ) {
            con.Relationship_Category_r__c = 'Member - past';
            updateCons.add(con);
        } 
    }
    update updateCons;
}