0

I have a dynamic SOQL that is being generated and then I am using database.query(querystring) to store the list of sObject in the dynamic sobject list.

Here's the code :

string queryString ='SELECT id';             
        for(string s : fieldNames){
            queryString += ', '+s;
        }
        system.debug('Case Id :'+objid);
        queryString += ' FROM ' + objName + ' WHERE id=\''+objId+'\'';

        system.debug('Query : '+queryString);

        List<sObject> results = Database.query(queryString);

this is the query it prints in dev console :

SELECT id, Case.Contact.FirstName, Case.Account.Name, Case.Account.website_active__c FROM Case WHERE id='5000R000005XydT'

the query here is for Case object but it can be any object that the query runs for. The results variable assignment looks like this:

23:11:01:062 VARIABLE_ASSIGNMENT [41]|results|[{"Id":"5000R000005XydTQAS","ContactId":"0030R00000flV9jQAE","AccountId":"0010R00000YyS2lQAF","RecordTypeId":"012o0000000ttBUAAY","Contact":{"Id":"0030R00000flV9jQAE","FirstName":"Test","RecordTypeId":"012o0000000tpuTAAQ"},"Account":{"Id":"0010R00000YyS2lQAF","Website_Active__c":"www.mercermarketplac (2..

When I iterate over the results it throws and error variable not exist

for(sObject s : results){
    system.debug(s.contact.name);
 }

How can I access the Contact and Account values if results is not null with list<sObject>, or can I not do that and have to make sure to declare the list with that particular sobject being queried like in this case list<case>?

I have referred to this question and , this question. But the difference is, they have requested to see fields for a specific object query always. I have a dynamic query which can be for any object, how can I retrieve those values using list<sObject>?

2

In order to get a parent sObject, you need to use getSobject, and to get a field from that, use get:

for(sObject s : results){
    system.debug(s.getSObject('Contact').get('Name'));
    system.debug(s.getSObject('Contact').getSObject('Account').get('Name'));
}

To do this dynamically, you'll probably want to write a generic method:

public static Object getValue(SObject record, String path) {
  try {
    SObject temp = record;
    String[] parts = path.split('\\.');
    while(parts.size() > 1) {
      temp = record.getSObject(parts.remove(0));
    }
    return temp.get(parts[0]);
  } catch(Exception e) {
    return null;
  }
}

This code should extract a value, or null if there isn't one:

for(sObject s : results){
    system.debug(getValue(s, 'Contact.Name'));
    system.debug(getValue(s, 'Contact.Account.Name'));
}
  • let me try this out, Thanks much for explaining much clearly. – apple123 Jun 19 at 14:08
  • this worked perfectly. Thank you. – apple123 Jun 19 at 15:19
  • if I have 3 levels then this is returning null, like if I need a field Docman_Communication__c.PrimaryInformation__r.Account.Website_Active__c and here when we get Contact it also has Account as an ID and the getValue() method has to be called agian, but how do I avoid that recursive and get value from account? – apple123 Jun 19 at 16:00
  • @apple123 You'd need to have gotten the record in to a variable. The recursion is necessary otherwise. – sfdcfox Jun 19 at 16:10
4

Apex is a strongly-typed language. When you have a variable the compiler knows to be a List<sObject>, it will only allow you to access fields on the individual sObject components of that list that are defined for the sObject class - which doesn't include Contact and Account-specific fields. That's why you receive a

Variable does not exist

error.

You have two options, one static and the other dynamic.

The first is to assign the result, or cast it, to a concrete type:

List<Contact> contacts = (List<Contact>)results;

That will fail at runtime with an exception if the list isn't really a List<Contact>.

The other is to use dynamic methods. With an sObject variable, you may call the method get() to obtain a field value, and getSobject() for a related object.

Note that get() returns an even more generic value - an Object. You'll again have to cast this to a concrete type to do much with it. getSobject() returns an sObject that acts the same as the ones you've already got, except that its actual underlying type may be different. For example, if you did someCase.getSobject('Contact'), your sObject returned would actually be a Contact - but the compiler doesn't know that at compile time.

  • Thank you, I will be sure to try out this. @sfdcfox has also responded, I will try that out too. – apple123 Jun 19 at 14:08

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.