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
blueandgoldblueandgold 

Learning how to bulkify trigger code, but stuck

Alright, as a newbie to bulkifying trigger code, I'm scratching my head on this one. I feel like I've read all I can on List collections, but I still can't figure how to get going in this situation.  Here's what we've got cooking.

 

Objects in play: CampaignMember, Campaign, Lead

 

Goal: after the insert of a new campaignmember record, convert the campaignmember's associated Lead record.

 

We created this without the bulkifying process, and as one would expect, when someone goes to add a bunch of campaignmembers to a campaign, our trigger fires, and often times quite quickly hits the SOQL governor limit due to queries within a loop.

 

Here's the core snippet of code we have created, unbulkified. I'm trying to learn how to get better at bulkifying things, and this one seems a bit complex.

 

trigger ECampaignMember on CampaignMember (after insert) {

    for(CampaignMember myCampaignMember: Trigger.new){

	        // Find the lead record related to this campaign member
    	    Lead l = [SELECT FirstName, LastName, Email, Street, City, State, PostalCode, RecordTypeId, IsConverted, RegistrationMatchReviewNeeded__c FROM Lead WHERE Id = :myCampaignMember.LeadId LIMIT 1];

	        // Find the name of the campaign that this campaign member is related to
    	    Campaign campaign = [SELECT Name FROM Campaign WHERE id = :myCampaignMember.CampaignId LIMIT 1];

        	// Find the RecordType ID for the Lead RecordType that has DeveloperName = Registration_Lead
	        RecordType rlrt = [SELECT Id FROM RecordType WHERE SobjectType = 'Lead' AND DeveloperName = 'Registration_Lead' LIMIT 1];

	        // Make sure this is a Registration lead record type. If not, don't do any of this.
    	    if(l.IsConverted==false && l.RecordTypeId == rlrt.id){

	            // Set the variables
    	        String c = '1';
        	    String a = '1';


	            Database.LeadConvert lc = new database.LeadConvert();
    	        lc.setLeadId(myCampaignMember.LeadId);

        	    // need to assign the conversion status to match the dropdown options
          	    lc.convertedStatus = 'Closed - Converted';

	            // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead. If not, don't create an opportunity record.
    	        if(l.IsConverted==false && l.RecordTypeId == rlrt.Id){

        	        // create a new opportunity upon conversion
            	    lc.setDoNotCreateOpportunity(false);

           		 } else {

            	    // create a new opportunity upon conversion
                	lc.setDoNotCreateOpportunity(true);

	            }

    	        // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead
        	    if((l.IsConverted==false && (l.RecordTypeId == rlrt.Id))){

            	    // name the opportunity in the format: "<firstname> <lastname> - <campaign_name> - Event Registration"
                	lc.setOpportunityName(l.FirstName + ' ' + l.LastName + ' - ' + campaign.Name + ' - Event Registration');

        	    }

	            // If there is an existing contact that matches on last name, first name, and email address...
    	        if(i>0){

        	        // set the contact ID
            	    lc.setContactId(c);

        	        // set the account ID
            	    lc.setAccountId(a);

	            }

    	    Database.LeadConvertResult lcr = Database.convertLead(lc);
        	System.assert(lcr.isSuccess());

        	}
		}
    }
}

 Now, I generally understand the following:

 

1) I need to get all the SOQL queries out from under the for loop

2) I need to build a list of the campaign members that I need to iterate through

 

The biggest challenge is that you can see down towards the bottom of the code, that I need to grab values in related objects (like the Campaign object), so that I can include them in the conversion process.  For instance, I need to get the name of the Campaign related to the current campaign member so that I can include that in the sting that will be used to create the new Opportunity record name upon conversion.

 

How the heck do I do that?

Thanks in advance for even the first step of help on this.  It's greatly appreciated.

 

Cheers! 

 

Navatar_DbSupNavatar_DbSup

Hi,

Try the below code as reference:

trigger ECampaignMember on CampaignMember (after insert)

{

 list<id> ids=new list<id>();

    for(CampaignMember myCampaignMember: Trigger.new)

 {

  ids.add(myCampaignMember.LeadId);

 }

 

         // Find the lead record related to this campaign member

         for(Lead l :[SELECT FirstName, LastName, Email, Street, City, State, PostalCode, RecordTypeId, IsConverted, RegistrationMatchReviewNeeded__c FROM Lead WHERE Id in :ids])

   {

 

         // Find the name of the campaign that this campaign member is related to

         Campaign campaign = [SELECT Name FROM Campaign WHERE id = :myCampaignMember.CampaignId LIMIT 1];

 

         // Find the RecordType ID for the Lead RecordType that has DeveloperName = Registration_Lead

         RecordType rlrt = [SELECT Id FROM RecordType WHERE SobjectType = 'Lead' AND DeveloperName = 'Registration_Lead' LIMIT 1];

 

         // Make sure this is a Registration lead record type. If not, don't do any of this.

         if(l.IsConverted==false && l.RecordTypeId == rlrt.id)

   {

 

             // Set the variables

             String c = '1';

             String a = '1';

 

 

             Database.LeadConvert lc = new database.LeadConvert();

             lc.setLeadId(myCampaignMember.LeadId);

 

             // need to assign the conversion status to match the dropdown options

               lc.convertedStatus = 'Closed - Converted';

 

             // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead. If not, don't create an opportunity record.

             if(l.IsConverted==false && l.RecordTypeId == rlrt.Id){

 

                 // create a new opportunity upon conversion

                 lc.setDoNotCreateOpportunity(false);

 

              } else {

 

                 // create a new opportunity upon conversion

                 lc.setDoNotCreateOpportunity(true);

 

             }

 

             // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead

             if((l.IsConverted==false && (l.RecordTypeId == rlrt.Id))){

 

                 // name the opportunity in the format: "<firstname> <lastname> - <campaign_name> - Event Registration"

                 lc.setOpportunityName(l.FirstName + ' ' + l.LastName + ' - ' + campaign.Name + ' - Event Registration');

 

             }

 

             // If there is an existing contact that matches on last name, first name, and email address...

             if(i>0){

 

                 // set the contact ID

                 lc.setContactId(c);

 

                 // set the account ID

                 lc.setAccountId(a);

 

             }

   

 

         Database.LeadConvertResult lcr = Database.convertLead(lc);

         System.assert(lcr.isSuccess());

 

         }

  }

}

 

Did this answer your question? If not, let me know what didn't work, or if so, please mark it solved. 

TejTej
Try this and let me know if you run into any issues, No more SOQL in for loop.
trigger ECampaignMember on CampaignMember (after insert) {
	
	map<CampaignMember, ID> camLeadMap = new map<CampaignMember, ID>();
	map<CampaignMember,ID> camCampaignIdMap =  new map<CampaignMember, ID>();
	map<ID,Lead> leadMap =  new map<ID, Lead>();
	map<ID,campaign> camMap =  new map<ID, campaign>();
	list<ID> leadList = new list<ID>();
	list<ID> campaignList = new list<ID>();
	
	RecordType rlrt = [SELECT Id FROM RecordType WHERE SobjectType = 'Lead' AND DeveloperName = 'Registration_Lead' LIMIT 1];
	
	for(CampaignMember myCampaignMember: Trigger.new){
		
		camLeadMap.put(myCampaignMember, myCampaignMember.LeadId);
		camCampaignIdMap.put(myCampaignMember, myCampaignMember.CampaignId);
	
	}
	
	leadList = camLeadMap.getValues();
	campaignList = camCampaignIdMap.getValues();
	
	for(Lead l : [SELECT FirstName, LastName, Email, Street, City, State, PostalCode, RecordTypeId, IsConverted, RegistrationMatchReviewNeeded__c FROM Lead WHERE Id IN :leadList]){
	
		leadMap.put(l.Id, l);
	
	}
	
	for( campaign c :[SELECT Name FROM Campaign WHERE id IN :campaignList]){
		
		camMap.put(c.Id, c);	
	}


	for(CampaignMember myCampaignMember: Trigger.new){

	        // Find the lead record related to this campaign member
    	//    Lead l = [SELECT FirstName, LastName, Email, Street, City, State, PostalCode, RecordTypeId, IsConverted, RegistrationMatchReviewNeeded__c FROM Lead WHERE Id = :myCampaignMember.LeadId LIMIT 1];
			
			Lead l = leadMap.get(myCampaignMember.LeadId);
			
	        // Find the name of the campaign that this campaign member is related to
    	//    Campaign campaign = [SELECT Name FROM Campaign WHERE id = :myCampaignMember.CampaignId LIMIT 1];
			
			Campaign campaign = camMap.get(myCampaignMember.CampaignId);
			
			
        	// Find the RecordType ID for the Lead RecordType that has DeveloperName = Registration_Lead
	  //      RecordType rlrt = [SELECT Id FROM RecordType WHERE SobjectType = 'Lead' AND DeveloperName = 'Registration_Lead' LIMIT 1];

	        // Make sure this is a Registration lead record type. If not, don't do any of this.
    	    if(l.IsConverted==false && l.RecordTypeId == rlrt.id){

	            // Set the variables
    	        String c = '1';
        	    String a = '1';


	            Database.LeadConvert lc = new database.LeadConvert();
    	        lc.setLeadId(myCampaignMember.LeadId);

        	    // need to assign the conversion status to match the dropdown options
          	    lc.convertedStatus = 'Closed - Converted';

	            // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead. If not, don't create an opportunity record.
    	        if(l.IsConverted==false && l.RecordTypeId == rlrt.Id){

        	        // create a new opportunity upon conversion
            	    lc.setDoNotCreateOpportunity(false);

           		 } else {

            	    // create a new opportunity upon conversion
                	lc.setDoNotCreateOpportunity(true);

	            }

    	        // If the lead is not already converted, AND if the lead record type has a DeveloperName = Registration_Lead
        	    if((l.IsConverted==false && (l.RecordTypeId == rlrt.Id))){

            	    // name the opportunity in the format: "<firstname> <lastname> - <campaign_name> - Event Registration"
                	lc.setOpportunityName(l.FirstName + ' ' + l.LastName + ' - ' + campaign.Name + ' - Event Registration');

        	    }

	            // If there is an existing contact that matches on last name, first name, and email address...
    	        if(i>0){

        	        // set the contact ID
            	    lc.setContactId(c);

        	        // set the account ID
            	    lc.setAccountId(a);

	            }

    	    Database.LeadConvertResult lcr = Database.convertLead(lc);
        	System.assert(lcr.isSuccess());

        	}
		}
    
}

 

blueandgoldblueandgold

Hi Navatar_DbSup and Tej,

 

Thanks for the good ideas.  I'm going to try both out, and let you know the results.  This is extremely helpful!