function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Silpi roy 16Silpi roy 16 

Trigger code error

 Cannot modify a collection while it is being iterated : Getting this error on this code please help and Too many SOQL Query for the below code.


trigger DeleteBillingItem on BillingItem__c (after insert) {
    set<Id> bID = new set<Id>();
    for(BillingItem__c bi:trigger.new){
       bID.add(bi.Id);
    }

    list<BillingItem__c>BItem = new list<BillingItem__c>();
    If(bID.isEmpty() == false){   
       BItem = [select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined'];
    }

    for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
       delete BI;
    }
Please advise
Best Answer chosen by Silpi roy 16
Khan AnasKhan Anas (Salesforce Developers) 
Try this:
 
trigger DeleteBillingItem on BillingItem__c (after insert) {
    set<Id> bID = new set<Id>();
    for(BillingItem__c bi:trigger.new){
       bID.add(bi.Id);
    }

    list<BillingItem__c>BItem = new list<BillingItem__c>();
    If(bID.isEmpty() == false){   
       BItem = [select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined'];
    }

List<BillingItem__c>bt = new List<BillingItem__c>();
for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
     bt.add(BI); 
}
if(bt.size()>0){
     DELETE bt;
}
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Regards,
Khan Anas

All Answers

Khan AnasKhan Anas (Salesforce Developers) 
Hi Silpi,

Greetings to you!

You are getting this error because you are using DML inside for loop. According to Salesforce doc,
  • Minimize the number of data manipulation language (DML) operations by adding records to collections and performing DML operations against these collections.
  • Minimize the number of SOQL statements by preprocessing records and generating sets, which can be placed in single SOQL statement used with the IN clause.

So, instead of:

for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
       delete BI;
    }

Use this:
List<BillingItem__c> bitem = new List<BillingItem__C>();
for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
     bitem.add(BI); 
}
if(bitem.size()>0){
     DELETE Bitem;
}


Please refer to below links for more information:
https://help.salesforce.com/articleView?id=000181404&type=1

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_bestpract.htm

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
Silpi roy 16Silpi roy 16
Hi Anas,

Tried with that code also in that case getting error as Cannot modify a collection while it is being iterated 
Khan AnasKhan Anas (Salesforce Developers) 
Try this:
 
trigger DeleteBillingItem on BillingItem__c (after insert) {
    set<Id> bID = new set<Id>();
    for(BillingItem__c bi:trigger.new){
       bID.add(bi.Id);
    }

    list<BillingItem__c>BItem = new list<BillingItem__c>();
    If(bID.isEmpty() == false){   
       BItem = [select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined'];
    }

List<BillingItem__c>bt = new List<BillingItem__c>();
for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
     bt.add(BI); 
}
if(bt.size()>0){
     DELETE bt;
}
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Regards,
Khan Anas
This was selected as the best answer
Raj VakatiRaj Vakati
Can you please explain what is your requirement .. I am sure what is the requirement to delete the same record after insert ... 

if that is the case you can validation .. 


YOU ARE passing the current record Id to query and trying to delete ..
 
select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined'

 
Raj VakatiRaj Vakati
Can you please explain what is your requirement .. I am sure what is the requirement to delete the same record after insert ... 

if that is the case you can validation .. 


YOU ARE passing the current record Id to query and trying to delete ..
 
select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined'

 
Silpi roy 16Silpi roy 16
Hi Raj,

yes deleting the items that are queried but the issue is items are synced from SAP

Thanks,
Silpi
Silpi roy 16Silpi roy 16
Hi @ Khan Anas,

Could you help me explaining your code.
What is the difference between the codes.

Thanks in Advance.
Raj VakatiRaj Vakati
Got it .. Your code looks good and can you check what is the batch size set  in SAP while uploading data into salesforce
Raj VakatiRaj Vakati
Or add limit 

 
trigger DeleteBillingItem on BillingItem__c (after insert) {
    set<Id> bID = new set<Id>();
    for(BillingItem__c bi:trigger.new){
       bID.add(bi.Id);
    }

    list<BillingItem__c>BItem = new list<BillingItem__c>();
    If(bID.isEmpty() == false){   
       BItem = [select id,BillingDocumentId__c,UnitPrice__c,Sub_Segment__c,Gross__c,NettoAmount2__c from BillingItem__c
                          where Id IN: bID AND BillingDocumentId__c!=Null
                       and (UnitPrice__c=0 OR UnitPrice__c=null) AND  Sub_Segment__c='Undefined' Limit 49999];
    }

List<BillingItem__c>bt = new List<BillingItem__c>();
for(BillingItem__c BI : BItem){
     System.debug('BI: '+BI);
     bt.add(BI); 
}
if(bt.size()>0){
     DELETE bt;
}
}

 
Khan AnasKhan Anas (Salesforce Developers) 
Hi Silpi,

The problem is that in your code you are modifying a list of records that you are iterating over.

for(BillingItem__c BI : BItem){
    Bitem.add(BI);
}
DELETE Bitem;

Bitem is the list that you are iterating over and again you are modifying the same list. That's why you get an error like Cannot modify a collection while it is being iterated.

So, I have used a different list to modify the list of records.
List<BillingItem__c>bt = new List<BillingItem__c>();

I hope it helps you.

Kindly mark this as solved if the information was helpful. It will help to keep this community clean.

Regards,
Khan Anas