You need to sign in to do that
Don't have an account?
DML insert statement within trigger
I need to create a trigger that will insert new records, but I cannot use a DML insert statement to create new records on the object that is firing the trigger.
Is there an alternative? Some other method to accomplish this?
Here is a stripped down prototype of what I'm trying to do:
trigger FullfillmentGetAccountHierarchy on Fulfillment__c (before insert) { // Other code occurs here to get the values dynamically for the hard-coded values below List<Fulfillment__c> fuls = new List<Fulfillment__c>(); for (Integer i = 0; i < 6; i++) { Fulfillment__c ful = new Fulfillment__c(); ful.Contact__c = '003S0000006owfN'; ful.Account__c = '001S000000AUd0r'; ful.Fulfillment_Request__c = 'a0AS000000214OJ'; fuls.add(ful); } insert(fuls); }
Is there any way to insert new records using a trigger on the object that fires the trigger? Any suggestions?
Thanks.
I tried to create a simple prototype using a @future method. I didn't get any errors, but the new records are not created?
Here is the trigger:
trigger FulfillmentAsyncInsert on Fulfillment__c (after insert) { FulfillmentAsyncTrigger.processRelatedAccounts(Trigger.newMap.keySet()); }
Here is the class with the method:
public class FulfillmentAsyncTrigger { @future public static void processRelatedAccounts(Set<Id> accountIds) { List<Account> accts = [Select Id, ParentId From Account Where Id in: accountIds]; // There is a lot of logic to pull the necessary data going on in this section, which I have // omitted for brevity // Here I'm just trying to prove the concept that the new fulfillment records will get inserted. List<Fulfillment__c> fuls = new List<Fulfillment__c>(); for (Integer i = 0; i < 6; i++) { Fulfillment__c ful = new Fulfillment__c(); ful.Contact__c = '003S0000006owfN'; ful.Account__c = '001S000000AUd0r'; ful.Fulfillment_Request__c = 'a0AS000000214OJ'; fuls.add(ful); } insert fuls; } }
Am I missing anything?
The future call looks like (apart from a small nitpick too, but you may want to not use the word trigger in your class (it's not a trigger)) but you are going to have recursion problems. Right now your process is:
after insert - call FullfillmentAsyncInsert
call future method - insert more Fullfillment__c objects
after insert - call FullfillmentAsyncInsert
call future method ........ and so on.
Also, I am assuming you are not really hardcoding ids in your trigger, and just doing in the post as an example. Hardcoding ids is never a good idea
I will rename the class, I just threw it in the sandbox environment since I'm just trying to prototype the functionality and get a working example. The same with the hardcoded values. It just used that as an example, I will be populating the field values dynamically.
I understand the recursion problem you've identified. Is there an example I might be able to take a look at to see how to prevent the recursion?
I'm still not clear on why the insert didnt' work using the @future method? Shouldn't I be getting new records added, even though I have the recursion problem.
Jeff Douglas has a great post on this: http://blog.jeffdouglas.com/2009/10/02/preventing-recursive-future-method-calls-in-salesforce/
HTH
One way of not getting into an infinite loop is to have a checkbox on the record that controls the propagation. For example you create a record that fires the trigger if the checkbox is true then you call the @future method. On the @future method you create records with this checkbox on false. So this time when the trigger is fired will not attempt to call the @future metho. In fact, calling a @future method from a @future thread throws an exception so that's one thing you don't want to do.
As for the recursion problem and the records not being inserted I guess this is exactly what happened. The @future executes and fires the insert trigger, this trigger tries to make an @future call and this throws an exception.
If you take a look at the debug logs I bet you will find the answer.