Search code examples
salesforceapexsoqlsalesforce-service-cloudsalesforce-communities

How to extract Parent.Parent field value from SOQL Query?


This is my query

SOBject acc = [Select Id, Name, (Select Id, Account.Parent.Parent.Name, Name from Contacts__r) from Sales_Location__c where Id ='a005j000009xxxBAxU'];
Contact abc =(Contact)(acc.getSobjects('Contacts__r')).get(0);
System.debug(abc.get('Account.Parent.Parent.Name'));

But instead of using get() if I directly use abc.Account.Parent.Parent.Name, I am getting result. But I don't know why my code fails in case of get(). In Actual scenario abc is of SObject type that's why I need to use get() here.


Solution

  • sObject.get() works on only 1 field, it will not travel via "dots". See https://salesforce.stackexchange.com/a/24804/799 (shameless plug, it's my own answer)

    You can try like that

    Sales_Location__c location = [Select Id, Name, 
        (Select Id, Account.Parent.Parent.Name, Name from Contacts__r)
        from Sales_Location__c 
        where Id ='a005j000009xxxBAxU'];
    
    if(!location.Contacts__r.isEmpty()){
        Contact abc = location.Contacts__r[0];
        if(abc.Account != null && abc.Account.Parent != null && abc.Account.Parent.Parent != null){
            System.debug(abc.Account.Parent.Parent.Name);
        } else {
            System.debug('there is no grandparent account');
        }
    }
    

    but this null checking gets very annoying after a while. There's a fairly recent addition https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SafeNavigationOperator.htm

    // the query is stupid, the parent name will always be null
    // but my point is it's accessed safely, it won't throw the
    // null reference exception
    Contact c = [SELECT Account.Parent.Name 
        FROM Contact 
        WHERE Account.ParentId = null
        LIMIT 1];
    System.debug(c.Account?.Parent?.Name);
    

    P.S. even if your function receives a generic sObject - you can always try to cast it back to the original

    Sales_Location__c loc = (Sales_Location__c) abc;

    So it'll give you simpler code later on, compile-time checks... Don't suffer with generic sobjects if you don't have to. Check instanceof too if your function can accept sobjects from multiple sources