Obtaining Single Record – SOQL vs. Instantiating New Object

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?

Answer

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();

Attribution
Source : Link , Question Author : Optimus , Answer Author : Adrian Larson

Leave a Comment