11

Background

I have a custom object which has a master/detail relationship to Opportunities. Whenever a record on this custom object is created or edited, I need to update the parent opportunity (and roll-up summary fields are too basic for my needs here).

Question

What is the best way to reference the parent object in order to update it? The way I see it, I have two options:

  1. Run a SOQL query
  2. Instantiate a new Opportunity object and assign it the correct ID (the value in the lookup field of the child record).

I know both work, but I don't know which one is the better option from a performance or best practice approach. Is one option preferred over the other?

1 Answer 1

16

Do not use SOQL unless you must. If all the data you need to update comes from the child, simply use it sans query. Save governor limits wherever possible in your code.

Opportunity master = new Opportunity(Id=detail.Opportunity__c);
// child related data
update master;

Sometimes you actually need parent data, and that is how you should decide when a query is acceptable. Only when necessary.

Opportunity master = [
    SELECT Necessary_Data__c
    FROM Opportunity
    WHERE Id = :detail.Opportunity__c
];
// further manipulation
update master;

There is another reason you might need to query. I have never really run into it, so I consider it a fairly esoteric concern. But if you have a high volume of updates to the records you wish to update, you may need to implement row locking and lock the records for the transaction with a FOR UPDATE clause. Use extreme care if you implement this clause and make sure to research the side-effects.

Opportunity lockedMaster = [
    SELECT Id
    FROM Opportunity
    WHERE Id = :detail.Opportunity__c
    FOR UPDATE
];

Just a note on bulkification. If you are updating parent records based on child data, you run the risk of duplicate records in your list. To avoid this risk, use a map.

Map<Id, Opportunity> parents = new Map<Id, Opportunity>();
for (Child__c child : children)
{
    parents.put(child.Opportunity__c, new Opportunity(/*...*/));
}
update parents.values();

2
  • 3
    However... Doing this on extremely busy objects might result in UNABLE_TO_LOCK_ROW exceptions and/or clobbering data. It's worth mentioning that "busy" objects should be queried with a FOR UPDATE to reduce the odds of data clobbering.
    – sfdcfox
    Commented Jul 11, 2016 at 18:44
  • @sfdcfox Good point, though I've never needed to use it myself. Updated.
    – Adrian Larson
    Commented Jul 11, 2016 at 19:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .