+ Start a Discussion
David DanzigDavid Danzig 

Trouble Populating a Lookup field while Creating a record in a Trigger

I work for a large multi-brnached organization and we have run out of custom fields on Contact and would like to use a corresponding custom object to hold more info. Before doing that, I want to make sure that there will be one and only one record on this new object for each Contact.  To that end, I've put together a very simple trigger to create a corresponding record in a custom object for each of our Contacts.

 

Everything works aside from populating the Contact__c lookup field on the custom object. I even repeated that command separately (not while making the new record) but it didn't work either. Any ideas on what's wrong?

 

 

trigger insertPIOPrec on Contact (before insert, before update) 
{
for(Contact c:Trigger.new)
{
If (c.PI_Ongoing_Participation__c == null){
PI_Ongoing_Participation__c p = new PI_Ongoing_Participation__c(Contact__c = c.Id);
p.Contact__c = c.Id;
insert p;
c.PI_Ongoing_Participation__c = p.Id;
}
else {}
}
}

 

Also, I'd like to upgrade the code to handle bulk inserts, but had a lot of difficulty figuring out how to do that.

 

Any help would be much appreciated.

 

Thanks,

David.

Best Answer chosen by Admin (Salesforce Developers) 
SuperfellSuperfell
The Contact object has no id populated yet when a before insert trigger is called, so for insert, i think you'll need to do it in an after insert trigger.

All Answers

SuperfellSuperfell
The Contact object has no id populated yet when a before insert trigger is called, so for insert, i think you'll need to do it in an after insert trigger.
This was selected as the best answer
ShikibuShikibu
To add to Simon's reply, your trigger seems to execute one insert per record. That's going to get you into governor trouble. Have a look at the Triggers and Bulk Requests section of the Apex guide.
David DanzigDavid Danzig

Thanks. I tried changing to after insert, but then received an error message when trying to create a new contact that: "System.Exception: Record is read-only: Trigger.insertPIOPrec: line 11, column 28" which refers to the lookup field on contact that looks up to the new record of the custom object. I checked in Field Security and on the Record Type and the field is not Read Only, so I don't understand what the problem is.

 

Also, could you give me a really quick tutorial on Lists, Sets, and Maps - I tried "bulkifying" the trigger, but couldn't figure out how to get it set up right.

 

Thanks.

David.

VinodVinod

comment the insert p and check it out.

David DanzigDavid Danzig
I commented out "insert p;" and created a Contact, but nothing happened at all - no new corresponding record, no Contact field updated. How does this help?
David DanzigDavid Danzig

Actually, I was wrong. I did that with the Trigger set to, before update, before insert.

 

I chgnaged it now to after update, after insert with the "insert p" commented out and ran into the same problem as before that a contact record won't Save since there's an error with the line:

c.PI_Ongoing_Participation__c = p.Id;

 Any more ideas?

Thanks,

David.

NikiVNikiV

In an "after insert" trigger, if you want to modify the Contact further you actually need to call an update to the Contact record.  Otherwise the trigger doesn't pass on your updates to the Contact record as it finishes with your processing - only a before trigger will capture and automatically save the changes you make to a trigger.new recordset inside the trigger. 

 

Try changing this to a before update only and test it out - that should work out.  So you just need to rejig the after insert to resave the Contact.

 

 

David DanzigDavid Danzig

I don't understand what you mean. When I set it to before insert, it doesn't catch the new record of the corresponding-to-Contact object in order to connect it to the Contact, so it seems that it has to be after insert. But then when i try to update it afterwards, it fails as either saying that the field is Read Only. I tried to put in an "update p;" but it wouldn't save since it can't call DML or something like that. I will try some more, but still can't figure this out.

 

It has to be simple enough right? Create a new record that has an Id in a lookup field to another record and then put the new record's Id into a lookup field on the Contact record.

 

Please continue with the ideas.

Thanks.

NikiVNikiV

Try this out - I don't have your custom objects/fields so this hasn't been compiled or tested, but it looks better.

  1. -- Use a list of PI records so that you only insert them all once
  2. -- Use a list of Contact records that need to be updated after the PI records have been created
  3. -- This was a bit tricky because we have to insert the PI records before we know what their ID is, and then want to retrieve the id corresponding to the Contact list we cycle through.  I used a Map to link a Contact id with its matching PI id.

 

You might need to play around to get it to compile but hopefully this will get you on the right path.

 

 

 

trigger insertPIOPrec on Contact (after insert) {
// make a list of Contacts that need an additional update
List<Contact> ContactList = new List<Contact>();
// make a list of Contacts with updated data
List<Contact> ContactUpd = new List<Contact>();
// list of PI records to create
List<PI_Ongoing_Participation__c> NewPI = new List<PI_Ongoing_Participation__c>();

// cycle through inserted Contacts to find which need a PIO created
for(Contact c: trigger.new) {
If (c.PI_Ongoing_Participation__c == null){
PI_Ongoing_Participation__c p = new PI_Ongoing_Participation__c(Contact__c = c.Id);
p.Contact__c = c.Id;
NewPI.add(p);
ContactList.add(c);
} //end if
} // end for loop
// insert PI records now
insert NewPI;

// make a map of Contact id to new PIO id records to use for populating Contact
Map<Id,Id> PIMap = new Map<Id,Id>();
// cycle through new PI records and build out map
for (PI_Ongoing_Participation__c pi : NewPI) {
PIMap.put(pi.contact__c, pi.id);
}

// finally go through Contact list and populate the PI field
for (Contact updC : ContactList) {
updC.PI_Ongoing_Participation__c = PIMap.get(updC.id);
ContactUpd.add(updC);
} // end for
// now update the Contacts with the new PI record
update ContactUpd;
}

 

 

 

Message Edited by NikiV on 07-13-2009 12:50 PM