+ Start a Discussion
neckrneckr 

Help with Trigger - Link child id to parent Id with DML Insert outside of loop

Hi,

 

I have been revising my trigger code as I had DML Insert statements inside my loop. I created a list and brought the DML statements outside of loop, but have ran into another issue as a result.  I need to create a contact and link the contact to the Bankruptcy_Judgements_Liens_Report__r custom object through the BJVLAgencyContact.ID lookup field.  When I insert outside of the loop, the actual contact ID is not captured since its not inserted.

 

 

trigger ConVerificationRecordSetup on Con_Service_Task_Request__c (after insert, after update) 
{
Set<ID> accID = new Set<ID>();
//map to contain Con_Service_Task_Request__c record's id as key and it's master Account record's ID as value
Map<ID, ID> mapST_Account = new Map<ID, ID>();
Map<ID, ID> mapPrincipalAcctCont = new Map<ID, ID>();
Map<ID, List<Trade_Reference_Report__c>> mapExistingTRVs = new Map<ID, List<Trade_Reference_Report__c>>();

List <Contact> listBJLVAgencyContact = new List<Contact>();
List <Bankruptcy_Judgements_Liens_Report__c> listBJLV = new 


for(Con_Service_Task_Request__c ST : trigger.new){
         //This "Con_Service_Task_Request__c" should be API Name of Master Detail relationship with the Account 
         accID.add(ST.Account__c);
         mapST_Account.put(ST.id , ST.Account__c);
         
         Contact Principalcontact=[SELECT ID FROM Contact WHERE AccountId = : ST.Account__c AND Contact_Type__c = 'Acct Principal Contact' limit 1];
         mapPrincipalAcctCont.put(ST.id, Principalcontact.ID); 
         
         List<Trade_Reference_Report__c> ExistingTRVs = [SELECT ID FROM Trade_Reference_Report__c WHERE Account__c = : ST.Account__c AND TRV_Work_Category__c = : ST.Category__c limit 3]; 
         mapExistingTRVs.put(ST.id, ExistingTRVs); 
    }
    
Map<Id,List<Account>> records = new Map<Id,List<Account>>();
for(Account a : [SELECT id , 
(select id from Bankruptcy_Judgements_Liens_Report__r) 

FROM Account 
WHERE id in : accID]) {
    if(!records.containsKey(a.id))  {
        records.put(a.id , new List<Account>());
    }
    records.get(a.id).add(a);   
}   

for (Con_Service_Task_Request__c ST : Trigger.new) {

//INSERT NEW BJLV RECORD IF REQUIRED AND DOES NOT YET EXIST 
if (records.get(mapST_Account.get(ST.id)).get(0).Bankruptcy_Judgements_Liens_Report__r.Size()  == 0) 

Contact BJLVAgencyContact = new Contact(AccountId = ST.Account__c , Contact_Type__c = 'BJLV Agency', LastName = 'Enter Last Name');
 listBJLVAgencyContact.add(BJLVAgencyContact);

Bankruptcy_Judgements_Liens_Report__c BJLV = new Bankruptcy_Judgements_Liens_Report__c(Account__c = ST.Account__c , BJLV_Agency_Contact__c = BJLVAgencyContact.ID ); //BJVLAgencyContact.ID does not exist at this stage since Insert //outside of the loop now   
 listBJLV.add(BJLV);
 
}


}
insert listBJLVAgencyContact;
insert listBJLV; //Does not link to Contact on Insert. How would I get it to link?
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Sonali BhardwajSonali Bhardwaj

This is not right way to use DML statements. You should not put DMLs under a loop.

Use this instead

public PageReference processSelected() {

List<Service_Categories__c> selectedServiceTasks = new List<Service_Categories__c>();

for(aServiceTask aST : getServiceTasks() ) {
if(aST.selected == true) {
selectedServiceTasks.add(aST.ST);
}
}
System.debug('These are the selected Service Tasks...');
List<Con_Service_Task_Request__c >Strs = new List<Con_Service_Task_Request__c >();
for(Service_Categories__c ST : selectedServiceTasks) {

servicecode = ST.Service_Name__c + ' - ' + countrycode + ' - ' + provincestatecode + ' - ' + city;

Product2 service = [SELECT id FROM Product2 WHERE ProductCode = : servicecode limit 1];

Con_Service_Task_Request__c newSTR = new Con_Service_Task_Request__c(Account__c = acctID, Service__c = service.id, Service_Code__c = servicecode, Service_Name__c = ST.Service_Name__c, Service_Area__c = servicearea, Country__c = country,
Province_State__c = provincestate, City__c = city, Postal_Zip_Code__c = postalzip, Category__c = category, Service_Task_Request_Status__c = 'Not Verified'); //Service__c = serviceid,
Strs.add(newSTR );
system.debug(ST);
}
try {
upsert Strs ;
}
catch (DmlException e) {

}

return null;
}

 This will solve your issue.

 

All Answers

Sonali BhardwajSonali Bhardwaj

Try this

for (Con_Service_Task_Request__c ST : Trigger.new) {

	//INSERT NEW BJLV RECORD IF REQUIRED AND DOES NOT YET EXIST 
	if (records.get(mapST_Account.get(ST.id)).get(0).Bankruptcy_Judgements_Liens_Report__r.Size()  == 0) {

		Contact BJLVAgencyContact = new Contact(AccountId = ST.Account__c , Contact_Type__c = 'BJLV Agency', LastName = 'Enter Last Name');
 		listBJLVAgencyContact.add(BJLVAgencyContact);
 
	}


}

insert listBJLVAgencyContact;

for (Integer i=0; i<Trigger.new.size(); i++) {
Bankruptcy_Judgements_Liens_Report__c BJLV = new Bankruptcy_Judgements_Liens_Report__c(Account__c = Trigger.new[i].Account__c , BJLV_Agency_Contact__c = listBJLVAgencyContact[i].id); 
 listBJLV.add(BJLV);


}

insert listBJLV; 

}

 

 

 

neckrneckr

I tried to expand your code to my other custom object that is very similiar, only difference is it has a Master Detail Lookup field to Con_Service_Task_Request__c.  I tried to use Trigger.new[i].id  to link the objects and I receive an error:

 

ConVerificationRecordSetup: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, ConVerificationRecordSetup: maximum trigger depth exceeded Con_Service_Task_Request trigger event AfterUpdate for [a0TT0000002jnZQ]

 

Is there something I am missing?

 

 

for (Con_Service_Task_Request__c ST : Trigger.new) {

	//INSERT NEW BJLV RECORD IF REQUIRED AND DOES NOT YET EXIST 
	if (records.get(mapST_Account.get(ST.id)).get(0).Bankruptcy_Judgements_Liens_Report__r.Size()  == 0) {

		Contact BJLVAgencyContact = new Contact(AccountId = ST.Account__c , Contact_Type__c = 'BJLV Agency', LastName = 'Enter Last Name');
 		listBJLVAgencyContact.add(BJLVAgencyContact);
 
	}

if (!ST.Service__r.Customer_Reference_Reports__c)
{
 
 Contact CRVContact1 = new Contact(AccountId = ST.Account__c , Contact_Type__c = 'CRV Contact', LastName = 'Enter Last Name');
 listCRVContact1.add(CRVContact1);
  



}

insert listBJLVAgencyContact;
insert listCRVContact1;

for (Integer i=0; i<Trigger.new.size(); i++) {
Bankruptcy_Judgements_Liens_Report__c BJLV = new Bankruptcy_Judgements_Liens_Report__c(Account__c = Trigger.new[i].Account__c , BJLV_Agency_Contact__c = listBJLVAgencyContact[i].id); 
 listBJLV.add(BJLV);

Customer_Reference_Report__c CRV1 = new Customer_Reference_Report__c(CRV_Service__c = Trigger.new[i].id, CRV_Account__c = Trigger.new[i].Account__c , CRV_Contact__c = listCRVContact1[i].Id, CRV_Principal_Contact__c = mapPrincipalAcctCont.get(Trigger.new[i].id));    
listCRV1.add(CRV1);
}

insert listBJLV; 
insert listCRV1; // Error points to this line.

}

 

 

Sonali BhardwajSonali Bhardwaj

Something is there in customer_reference_report__c which is causing your this trigger to fire again and again. Reason might be:

- Con_Service_Task_Request__c has a rollup summary field on customer_reference_report__c.

- customer_reference_report__c has an insert trigger which again calls the trigger of Con_Service_Task_Request__c.

 

Check out whether you have above given scenario.

 

 

neckrneckr

Yes I have two roll up summary fields in Con_Service_Task_Request__c that summarize customer_reference_report__c.  The roll up field is used to check the the total number of references and the total number of passed reference checks

 

I do not have another Trigger in customer_reference_report__c

 

My Roll Up Summaries in Con_Service_Task_Request__c are below.

 

Do I need to remove these for my trigger to work?


CRV_Verified_Status_SUM__cRoll-Up Summary (SUM Customer Reference Report)
 CRV_Record_Count__c

Roll-Up Summary (COUNT Customer Reference Report)

 

Sonali BhardwajSonali Bhardwaj

Declare a class

 

public Class FireTrigger{
private static boolean runTrigger = true;
public static boolean getRun(){
if(runTrigger ){
runTrigger =false;
return true;
}
else{
return runTrigger;
}
}
}

 Now use this static variable in your trigger

 

 

trigger ConVerificationRecordSetup on Con_Service_Task_Request__c (after insert, after update) {

if (FireTrigger.getRun()) {

// put your whole trigger logic here.


}


}

 

 

neckrneckr

Just to clarify, I have to wrap this around the insert listCRV1; ?

insert listCRV1; 
neckrneckr

Thank you for your help!

Your Class and condition allows me to process with no errors.  However for some reason when I try to insert multiple records at once, only the first ST creates the desired output of  creating CRVContact1, CRVContact2, and CRVContact3  and its associated CRV1, CRV2 and CRV3. I copied my entire Trigger code because I have no clue why this is happening and can't tell you if the Class and condition I added is the cause since it wasn't processing at all before.

 

 

 

Sonali BhardwajSonali Bhardwaj

Can you tell me the way, how you are inserting multiple records at once?

neckrneckr

Through method in controller from VF page.  I am selecting multiple Service Tasks and processing all at once.

 

 

public PageReference processSelected() {

    List<Service_Categories__c> selectedServiceTasks = new List<Service_Categories__c>();
    
    for(aServiceTask aST : getServiceTasks() ) {
        if(aST.selected == true) {
        selectedServiceTasks.add(aST.ST);
        }
     }
     System.debug('These are the selected Service Tasks...');
     for(Service_Categories__c ST : selectedServiceTasks) {
           
     servicecode = ST.Service_Name__c + ' - ' + countrycode + ' - ' + provincestatecode + ' - ' + city;
     
     Product2 service = [SELECT id FROM Product2 WHERE ProductCode = : servicecode limit 1]; 
     
     Con_Service_Task_Request__c newSTR = new Con_Service_Task_Request__c(Account__c = acctID, Service__c = service.id, Service_Code__c = servicecode, Service_Name__c = ST.Service_Name__c, Service_Area__c = servicearea, Country__c = country, 
     Province_State__c = provincestate, City__c = city,  Postal_Zip_Code__c = postalzip, Category__c = category,  Service_Task_Request_Status__c = 'Not Verified'); //Service__c = serviceid, 
     
     try {upsert newSTR;
     } catch (DmlException e) {
        
     }    
     
     system.debug(ST);
     }
     return null;

 

 

Sonali BhardwajSonali Bhardwaj

This is not right way to use DML statements. You should not put DMLs under a loop.

Use this instead

public PageReference processSelected() {

List<Service_Categories__c> selectedServiceTasks = new List<Service_Categories__c>();

for(aServiceTask aST : getServiceTasks() ) {
if(aST.selected == true) {
selectedServiceTasks.add(aST.ST);
}
}
System.debug('These are the selected Service Tasks...');
List<Con_Service_Task_Request__c >Strs = new List<Con_Service_Task_Request__c >();
for(Service_Categories__c ST : selectedServiceTasks) {

servicecode = ST.Service_Name__c + ' - ' + countrycode + ' - ' + provincestatecode + ' - ' + city;

Product2 service = [SELECT id FROM Product2 WHERE ProductCode = : servicecode limit 1];

Con_Service_Task_Request__c newSTR = new Con_Service_Task_Request__c(Account__c = acctID, Service__c = service.id, Service_Code__c = servicecode, Service_Name__c = ST.Service_Name__c, Service_Area__c = servicearea, Country__c = country,
Province_State__c = provincestate, City__c = city, Postal_Zip_Code__c = postalzip, Category__c = category, Service_Task_Request_Status__c = 'Not Verified'); //Service__c = serviceid,
Strs.add(newSTR );
system.debug(ST);
}
try {
upsert Strs ;
}
catch (DmlException e) {

}

return null;
}

 This will solve your issue.

 

This was selected as the best answer