0
     List<Sobject> oppty = [SELECT Id, StageName, Account.Name, Account.Rating 
            FROM Opportunity where Name='Sample' And CloseDate= :DateToday];
    Oppty.put((Account)oppty.getSobject('Account').Name,'New Line Cinema');//Here I am 
trying to update the account name field but this was giving me error that invalid name variable

In the above query I am using sobject notation and also, I am querying single opportunity with mentioned conditions in the 'where' clause. Note -> DateToday is a variable in which I am storing todays date.

From the above SOQL query How can I access Parent fields through Sobject class methods?

Also, can I update parent object fields using the above query? If so, then please explain with an example. Thanks In Advance

2
  • 1
    Hi. Please edit your question to show what you have tried and where you are stuck. Take a look at How to Ask for an outline of what we expect from you when asking a question.
    – Phil W
    Commented Jan 2 at 7:13
  • Hi @PhilW I have updated my code and added the comments Commented Jan 2 at 14:08

2 Answers 2

1

When updating an SObject (generically or explicitly) it is always best to avoid including other fields that are not being updated.

@Tushar's answer covers several aspects of what you want to do, via use of SObject, SObject.get and SObject.getSObject. However, his answer includes a flaw when wanting to update one or more fields in an SObject returned as a related object ("parent"). If you simply use the SObject itself (here using "Account") then set one or more field values, when you perform the DML with that SObject all the queried fields AND the set fields get written back to the database. For any org that has more than one user, this can cause race conditions and data loss because one of the queried fields may have been updated concurrently, by a separate user, and this approach will cause that updated data to be overwritten with the original value.

Instead, you should use an approach like:

// Example query
List<SObject> child = [
        SELECT Id, StageName, Account.Name, Account.Rating 
            FROM Opportunity
            WHERE Name = 'Sample'
                AND CloseDate = :Date.today()];

// How to manage the data generically (e.g. so all the field names etc. could come from configuration)
SObject parent = child.getSObject('Account');
SObject parentToUpdate = parent.getSObjectType().newSObject(parent.Id);

parentToUpdate.put('Rating', 'Hot');

update parentToUpdate;

There are a few points to note here:

  1. Whenever you include a related object (a "parent") in an SOQL query, you do not need to explicitly query its ID - this is always automatically included in the results, which is why I can use parent.Id even though the query did not explicitly include either AccountId or Account.Id.
  2. By using the SObject's SObjectType and generating a new instance with an ID I have an entirely empty version of the given record, with the correct type, all done generically.
  3. Only the explicitly put fields' values will be updated by the update statement because these are the only field(s) that have been set in the version of the record used in the update.

Your example fails because you are trying to set the value of a field of oppty where that field's name is being provided by querying the related Account's name.

1

To access parent fields through sObject class methods, you can use the getsObject method to get the parent record as an sObject, and then use the get method to get the value of a specific field.

For example, you can use the following code to access the Account Name and Rating fields from the Opportunity record:

List<Sobject> oppty = [SELECT Id, StageName, Account.Name, Account.Rating 
    FROM Opportunity WHERE Name = 'Sample' AND CloseDate = :DateToday];


// Get the first opportunity record from the list
SObject opp = oppty[0];
// Get the account record as an SObject
SObject acc = opp.getSObject('Account');
// Get the account name and rating as strings
String accName = (String) acc.get('Name');
String accRating = (String) acc.get('Rating');
system.debug('accName :: '+accName);
system.debug('accRating :: '+accRating);

To update parent object fields using the above query, you can use the put method to set the value of a specific field, and then use the update statement to save the changes to the database.

For example, you can use the following code to update the Account Rating field to 'Hot':

List<Sobject> oppty = [SELECT Id, StageName, Account.Name, Account.Rating 
        FROM Opportunity WHERE Name = 'Sample' AND CloseDate = :DateToday];
// Get the first opportunity record from the list
SObject opp = oppty[0];
// Get the account record as an SObject
SObject acc = opp.getSObject('Account');
// Set the account rating to 'Hot'
acc.put('Rating', 'Hot');
// Update the account record in the database
update acc;
String accName = (String) acc.get('Name');
String accRating = (String) acc.get('Rating');
system.debug('accName :: '+accName);
system.debug('accRating :: '+accRating);
3
  • 2
    This will update the queried Account SObject with all fields that were originally queried, which is a bad idea from a concurrency perspective - the queried fields that have not been changed will cause those fields to be reset if changed concurrently by someone else.
    – Phil W
    Commented Jan 2 at 7:16
  • Hi Phil Could you please explain you statement with an example Commented Jan 2 at 14:17
  • Still has the same issue.
    – Phil W
    Commented Jan 2 at 14:50

You must log in to answer this question.

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