14

I'm writing a trigger for new opportunity products to populate a field Product_Category__c (on opportunity lineitem) getting the value from Product_Category_new__c (on Product).

This is my trigger:

trigger SetProductCategory on OpportunityLineItem (after insert) {

    for (OpportunityLineItem opplineitem: Trigger.new) {           
        opplineitem.Product_Category__c =  opplineitem.PricebookEntry.Product2.Product_Category_new__c;
    }     
}

I get this error message:

execution of AfterInsert caused by: System.FinalException: Record is read-only

I have tried with before insert;in this case there aren't errors but the value Product category it's not saved on Opportunity Line item.

I have found that:

In a after insert trigger is not allowed change field using trigger.new

Please can you suggest a solution for this? i would like to copy the value Product category (Product) on Product Category (Opportunity Product) after the insert of the new opportunity products.

Thanks in advantage for any advice.

Br

26

The record is locked because you are catching the record after the insert DML statement has happened. So if you'd like to modify this record (or records), you will need to query anew, modify, then execute another DML statement.

Here is an example of how you could modify your trigger to work:

trigger SetProductCategory on OpportunityLineItem (after insert) {

    List<OpportunityLineItem> olis = [SELECT Id, PricebookEntry.Product2.Product_Category_new__c FROM OpportunityLineItem WHERE Id IN: Trigger.newMap.keySet()];

    for (OpportunityLineItem opplineitem: olis){
        opplineitem.Product_Category__c= opplineitem.PricebookEntry.Product2.Product_Category_new__c;
    }

    update olis;

}

And of course, since it's a trigger, we want to be sure to work in batches -- that's why I'm updating a list of olis rather than an individual opp line item.

  • Thanks a lot Tim, but i get again the same error, in your code your are not changing the records in the list olis.Thanks again – Enry Aug 3 '13 at 7:31
  • Tim thanks to you i have found a solution.Check it!Thanks a lot for your help! – Enry Aug 3 '13 at 7:44
  • Oh sorry, typo on my part. I've corrected it. – Tim Smith Aug 3 '13 at 7:47
  • 3
    You could also do this in a before insert trigger if needed by getting all of the PricebookEntryID's and creating a map of PricebookEntryIDs to the PriceBookEntry records with the fields you want. Then updating the product category using that map. This would stop any update trigger from firing. – Eric Mar 5 '14 at 4:09
2

I know this issue is pretty old, but today I stumbled over an alternative solution by accident. As an apex developer for years, I'm avoiding database calls whenever I can, to save the Limits, so this solution might help someone to overcome data related limit exceptions.

Alternative Solution:

The records can be re-initialized as mutable objects, by serializing and deserializing the list. It runs about twice as fast as a database query, doesn't affect the query and row limits, but consumes more heap.

List<Account> accounts = (List<Account>) 
    JSON.deserialize(JSON.serialize(Trigger.new), List<Account>.class);

After some testing I came up with some details about the heap:

  • Deserialized records consum 1/4 more of the heap (don't ask me why, debugging displays two equivalent lists).
  • It also needs a lot of heap during processing (that is released after deserializing).
  • I was able to run it for about 18.000 records with selecting no more fields than their Id, before reaching the heap limit during the serializing process.
  • Fascinating find! What do you mean about "doesn't need query and row limits"? – Brian Miller Apr 8 at 7:18
  • @BrianMiller Total number of SOQL queries issued (= 100 queries) & Total number of records retrieved by SOQL queries (= 50.000 rows). With this solution, both are not affected. (I changed the wording a bit, thanks for your hint :) ) – Basti Apr 8 at 8:53
  • Thanks for the update. I don't see a SOQL query here, so I'm not sure how I would use your new technique and how it magically doesn't count against the query & row count limits – Brian Miller Apr 8 at 13:06
  • 1
    Just compare it to the other answer. You had to re query the data, now you don't have to anymore. – Basti Apr 8 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.