You need to sign in to do that
Don't have an account?
ilewi121
I am building a trigger to automatically associate a custom Account child object with a custom Opportunity child object. My trigger works fine and tests perfectly, except when I went to upload a bunch of records to the new object, I received the following error on every item:
System.LimitException: Apex CPU time limit exceeded
I found a helpful article here:
http://salesforce.stackexchange.com/questions/22223/how-to-code-more-efficient-to-avoid-apex-cpu-time-limit-exceeded
But I'm still not sure what I'm doing wrong. Does anyone have any ideas?
Here is the trigger code:
<pre>
trigger associateOppChildtoAccChild on OppChild__c (before insert, before update) {
Set<Id> OppSet = new Set<Id>();
for(OppChild__c OppChild :Trigger.new){
OppSet.add(OppChild.Opportunity__c);
}
Map<ID,ID> OPP_ACC = new Map<ID,ID>();
Set<Id> AccSet = new Set<Id>();
for(Opportunity OPP:[SELECT Id, AccountId from Opportunity where Id in :OppSet]){
OPP_ACC.put(OPP.Id, OPP.AccountId);
AccSet.add(OPP.AccountId);
}
Map<ID,ID> ACC_OppChild = new Map<ID,ID>();
for(OppChild__c OppChild :Trigger.new){
for(ID OPP :OPP_ACC.keyset()){
if(OPP == OppChild.Opportunity__c){
ACC_OppChild.put(OPP_ACC.get(OPP), OppChild.Id);
}
}
}
List<AccChild__c> AccChildList = [SELECT Id, Account__c, Type__c, Annual_Spend__c, Number_of_Shipment_Transactions__c FROM AccChild__c WHERE Account__c in :AccSet];
for(OppChild__c OppChild :Trigger.new){
for(AccChild__c m: AccChildList){
if(m.Type__c == OppChild.AccChild_Type__c){
for(ID ACC :ACC_OppChild.keyset()){
if(ACC == m.Account__c){
OppChild.AccChild__c = m.Id;
System.debug('OppChild AccChild = ' + OppChild.AccChild__c);
OppChild.Annual_Spend__c = m.Annual_Spend__c;
OppChild.Number_of_Shipment_Transactions__c = m.Number_of_Shipment_Transactions__c;
} else {
OppChild.adderror(OppChild.AccChild_Type__c + ' AccChild must exist on Account to add OppChild');
}
}
}
}
}
}
</pre>
How to prevent "Apex CPU Time Limit Exceeded"?
I am building a trigger to automatically associate a custom Account child object with a custom Opportunity child object. My trigger works fine and tests perfectly, except when I went to upload a bunch of records to the new object, I received the following error on every item:
System.LimitException: Apex CPU time limit exceeded
I found a helpful article here:
http://salesforce.stackexchange.com/questions/22223/how-to-code-more-efficient-to-avoid-apex-cpu-time-limit-exceeded
But I'm still not sure what I'm doing wrong. Does anyone have any ideas?
Here is the trigger code:
<pre>
trigger associateOppChildtoAccChild on OppChild__c (before insert, before update) {
Set<Id> OppSet = new Set<Id>();
for(OppChild__c OppChild :Trigger.new){
OppSet.add(OppChild.Opportunity__c);
}
Map<ID,ID> OPP_ACC = new Map<ID,ID>();
Set<Id> AccSet = new Set<Id>();
for(Opportunity OPP:[SELECT Id, AccountId from Opportunity where Id in :OppSet]){
OPP_ACC.put(OPP.Id, OPP.AccountId);
AccSet.add(OPP.AccountId);
}
Map<ID,ID> ACC_OppChild = new Map<ID,ID>();
for(OppChild__c OppChild :Trigger.new){
for(ID OPP :OPP_ACC.keyset()){
if(OPP == OppChild.Opportunity__c){
ACC_OppChild.put(OPP_ACC.get(OPP), OppChild.Id);
}
}
}
List<AccChild__c> AccChildList = [SELECT Id, Account__c, Type__c, Annual_Spend__c, Number_of_Shipment_Transactions__c FROM AccChild__c WHERE Account__c in :AccSet];
for(OppChild__c OppChild :Trigger.new){
for(AccChild__c m: AccChildList){
if(m.Type__c == OppChild.AccChild_Type__c){
for(ID ACC :ACC_OppChild.keyset()){
if(ACC == m.Account__c){
OppChild.AccChild__c = m.Id;
System.debug('OppChild AccChild = ' + OppChild.AccChild__c);
OppChild.Annual_Spend__c = m.Annual_Spend__c;
OppChild.Number_of_Shipment_Transactions__c = m.Number_of_Shipment_Transactions__c;
} else {
OppChild.adderror(OppChild.AccChild_Type__c + ' AccChild must exist on Account to add OppChild');
}
}
}
}
}
}
</pre>
<pre>trigger associateOppChildtoAccChild on OppChild__c (before insert, before update) {
Set<Id> AccSet = new Set<Id>();
for(OppChild__c OppChild :Trigger.new){
AccSet.add(OppChild.AccountId__c);
}
List<AccChild__c> AccChildList = [SELECT Id, Account__c, Type__c, Annual_Spend__c, Number_of_Shipment_Transactions__c FROM AccChild__c WHERE Account__c in :AccSet ];
for(OppChild__c OppChild :Trigger.new){
for(AccChild__c m: AccChildList){
if(m.Type__c == OppChild.AccChild_Type__c && m.Account__c == OppChild.AccountId__c){
OppChild.AccChild__c = m.Id;
System.debug('OppChild AccChild = ' + OppChild.AccChild__c);
OppChild.Annual_Spend__c = m.Annual_Spend__c;
OppChild.Number_of_Shipment_Transactions__c = m.Number_of_Shipment_Transactions__c;
}
}
}
}</pre>
For those who would like more information on using maps, though, I did find some good articles:
http://salesforce.stackexchange.com/questions/22223/how-to-code-more-efficient-to-avoid-apex-cpu-time-limit-exceeded
http://stackoverflow.com/questions/9521740/apex-map-within-a-map
http://www.x2od.com/2012/07/25/populate-map-without-fo-loops
https://developer.salesforce.com/forums?id=906F00000008yc1IAA
All Answers
Please refer below blog to understand and overcome this limit:
http://cloudyworlds.blogspot.in/2013/10/battling-cpu-time-out-limit-in-apex-sfdc.html
Does anyone know how I could optimize this code and remove some of the loops?
I'm thinking maybe I could put a map inside a map, but how would I do that? This article has some ideas, but I'm having trouble applying it to my scenario:
http://stackoverflow.com/questions/9521740/apex-map-within-a-map
<pre>trigger associateOppChildtoAccChild on OppChild__c (before insert, before update) {
Set<Id> AccSet = new Set<Id>();
for(OppChild__c OppChild :Trigger.new){
AccSet.add(OppChild.AccountId__c);
}
List<AccChild__c> AccChildList = [SELECT Id, Account__c, Type__c, Annual_Spend__c, Number_of_Shipment_Transactions__c FROM AccChild__c WHERE Account__c in :AccSet ];
for(OppChild__c OppChild :Trigger.new){
for(AccChild__c m: AccChildList){
if(m.Type__c == OppChild.AccChild_Type__c && m.Account__c == OppChild.AccountId__c){
OppChild.AccChild__c = m.Id;
System.debug('OppChild AccChild = ' + OppChild.AccChild__c);
OppChild.Annual_Spend__c = m.Annual_Spend__c;
OppChild.Number_of_Shipment_Transactions__c = m.Number_of_Shipment_Transactions__c;
}
}
}
}</pre>
For those who would like more information on using maps, though, I did find some good articles:
http://salesforce.stackexchange.com/questions/22223/how-to-code-more-efficient-to-avoid-apex-cpu-time-limit-exceeded
http://stackoverflow.com/questions/9521740/apex-map-within-a-map
http://www.x2od.com/2012/07/25/populate-map-without-fo-loops
https://developer.salesforce.com/forums?id=906F00000008yc1IAA
trigger UpdateRelIntConIds5 on Contract_Group_Association__c (after delete, after insert, after update) {
Set<Id> accounts = new Set<Id>();
Set<Id> cons = new Set<Id>();
if (Trigger.old != null) {
system.debug('inside update');
for (Contract_Group_Association__c c : Trigger.old) {
if (c.Internal_Contract_Group__c != null)
cons.add(c.Internal_Contract_Group__c);
}
}
if (Trigger.new != null) {
system.debug('inside insert');
for (Contract_Group_Association__c c : Trigger.new) {
if (c.Internal_Contract_Group__c != null)
cons.add(c.Internal_Contract_Group__c);
}
}
List<Customer_Groups_Association__c> conGroup = [select Internal_Contact_Group__c from Customer_Groups_Association__c where Internal_Contract_Group__c in :cons];
system.debug('conGroup'+conGroup.size());
for (Customer_Groups_Association__c cx : conGroup) {
accounts.add(cx.Internal_Contact_Group__c);
system.debug('cx.Internal_Contact_Group__c: '+cx.Internal_Contact_Group__c);
}
system.debug('Groups'+accounts);
UpdateRelatedInternalContractIds ur = new UpdateRelatedInternalContractIds(accounts);
ur.go();
}
Related apex class :
global class UpdateRelatedInternalContractIds {
public Set<Id> accounts {get; set;}
public UpdateRelatedInternalContractIds(Set<Id> accounts) {
this.accounts = accounts;
}
public void go() {
Set<Id> contractGroups = new Set<Id>();
Map<String, Set<String>> customers = new Map<String, Set<String>>();
if (accounts == null)
return;
List<Customer_Groups_Association__c> clist = [select id, Internal_Contract_Group__c, Internal_Contact_Group__c from Customer_Groups_Association__c where Internal_Contact_Group__c in :accounts];
if (clist != null) {
for (Customer_Groups_Association__c c : clist) {
contractGroups.add(c.Internal_Contract_Group__c);
Set<String> t = customers.get(c.Internal_Contact_Group__c);
if (t == null) {
t = new Set<String>();
customers.put(c.Internal_Contact_Group__c, t);
}
t.add(c.Internal_Contract_Group__c);
}
}
Map<String, Set<String>> contractIds = new Map<String, Set<String>>();
List<Contract_Group_Association__c> dlist = [select id, Internal_Contract__r.Internal_Contract_ID__c, Internal_Contract_Group__c from Contract_Group_Association__c where Internal_Contract_Group__c in :contractGroups];
if (dlist != null) {
for (Contract_Group_Association__c d : dlist) {
Set<String> t = contractIds.get(d.Internal_Contract_Group__c);
if (t == null) {
t = new Set<String>();
contractIds.put(d.Internal_Contract_Group__c, t);
}
t.add(d.Internal_Contract__r.Internal_Contract_ID__c);
}
}
List<Account> customerList = [select id, Related_Internal_Contract_IDs__c from Account where id in :accounts];
for (Account c : customerList) {
String result = '';
if (customers.containsKey(c.id)) {
system.debug('customer@@' + c);
for (String s : customers.get(c.id)) {
if (!contractIds.containsKey(s))
continue;
for (String x : contractIds.get(s)) {
if (result != '')
result += ',';
result += x;
}
}
}
c.Related_Internal_Contract_IDs__c = result;
}
update customerList;
}
}