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
the0nly0nethe0nly0ne 

Creating Records, the Bulk-Safe Way

Hi,

 

I have been working on "bulkifying" my Apex, and lowering overall SOQL usage. I am running into a slight problem with creating a new record.

 

Usually, I include the syntax to create a new record within a for loop, under the trigger.new record; however, when running mass updates, I get the 21 SOQL limit error. When I put the new-record syntax outside the for loop, I don't get the error; but, it only creates one record, which is related to the entire batch rather than creating a new entry for every record that passes through the update.

 

My original code creates a record for each entry being updated, but hits SOQL limits in bulk:

 

for(Lead l:trigger.new){ Custom_Object__c co = new Custom_Object__c(); insert co; l.Custom_Lookup__c=co.Id; }

 

My updated code is not getting the SOQL error, but only creates one record for the entire batch (rather than 200 records, one for each):

 

Custom_Object__c co = new Custom_Object__c(); insert co; for(Lead l:trigger.new){ l.Custom_Lookup__c=co.Id; }

 

Does anyone have any suggestions or ideas on how I can fix this issue, and still keep my code "bulk-safe". I need to create a record for each entry that passes through the update, without hitting the SOQL limit. Any help you can give me would be highly appreciated.

 

Thanks!

jeffdonthemic2jeffdonthemic2

Instead of inserting your record one at a time, add each record inside your loop to a list and then insert the entire list.

 

 

List<Custom_Object__c> myList = new List<Custom_Object__c>();for(Lead l:trigger.new){ Custom_Object__c co = new Custom_Object__c(); // do some stuff before myList.add(co);}insert myList;

 

HTH

 

Jeff Douglas

Appirio, Inc.

http://blog.jeffdouglas.com 

 

the0nly0nethe0nly0ne

Thanks for the response. I changed my code, and all the records are getting inserted as expected; however, it is not letting me assign the new record ID to the lead, so the records are not related after triggering.

 

 

List<Custom_Object__c> mylist = new List<Custom_Object__c>();

for(Lead l:trigger.new){
Custom_Object__c co = new Custom_Object__c();

mylist.add(co);
l.Custom_Lookup__c=co.Id;
}

insert mylist;

 

I think this might be a problem because I am basically trying to create a parent record. Even if I open a new for loop after the records are inserted, it wouldn't be able to determine which record goes where, as far as I can think of. To further complicate things, I am trying to do this upon inserting the lead, so the lead doesn't actually have an ID to reference.

 

If you have any ideas, it would be greatly appreciated; however, I can already see a possible work-around, but it would involve rewriting many, many lines of code elsewhere to account for the change.

 

Thanks again!

 

Message Edited by the0nly0ne on 08-31-2009 12:57 AM
IanRIanR

You can use a map to hold a new instance of your custom object, indexed by the lead Id (run the trigger after insert so the Lead will be in the database, and you will have the Id).

 

You'll need to iterate through again, and build another collection of Leads, because the  post-insert ones in Trigger.new are read-only...

 

something like :

 

  

trigger MyLeadTrigger on Lead (after insert) {

Map<Id, MyObject__c> myMap = new Map<Id, MyObject__c>();

Set<Id> updateLeads = new Set<Id>();

for (Lead l : Trigger.new) {

system.debug('lead = ' + l);

updateLeads.add(l.Id);

MyObject__c co = new MyObject__c(Name='Object_'+l.Name);

myMap.put(l.Id, co);

}

insert myMap.values();

Map<Id, Lead> leads = new Map<Id, Lead>([SELECT Id FROM Lead WHERE Id in: updateLeads]);

for (Lead l : Trigger.new) {

Lead updLead = leads.get(l.Id);

updLead.Custom_Object__c = myMap.get(l.Id).Id;

}

update leads.values();

}

 

 

 HTH, Ian

 

:)