Once a parent(Contact) is selected I have to display a list of related records from child, grandchild and grandchild's child in one single page block. All the objects are in a lookup relationship with their parent. The query which I'm writing is not getting saved and giving the error: "Didn't understand relationship 'Grandchild__r' in FROM part of query call. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name." Please help me with apex, Wrapper class and VF code as well. Parent- Contact Child- Child__c Grandchild- Grandchild__c Grandchild's child- GreatGrandChild__c Below is my code.


public with sharing class MyController {    
Public String name {get;set;}
Public String newContactName{get;set;}
Public Contact objContact{get;set;}
Public List<Child__c> cmList{get;set;}
Public List<Wrapper> wrapList{get;set;}
public Boolean flag{get;set;}
Public MyController(){
    flag =  true;
  objContact = new Contact(); 

Public PageReference doSave(){
        insert objContact;
    }catch(Exception e){
        System.Debug('In catch '+e.getMessage());
    return null;
public List<SelectOption> getContactList(){
    List<SelectOption> contactList = new List<SelectOption>();
    contactList.add(new SelectOption('-----Select----','-----Select----')); 
    List<Contact> conList = [select id , Name from Contact];
    for(Contact c :conList){
        contactList.add(new SelectOption(c.Id,c.Name));     
   return  contactList;    

Public void showrecord(){
    wrapList = new List<Wrapper>();
    cmList = [Select id, Name, Contact__c, FieldA__c, (Select id, Name, Child__c, FieldB__c (Select id, Name, GrandChild__c, FieldC__c from GreatGrandChild__r) from GrandChild__r) from Child__c where Contact__c =: name];
    for(Child__c cm :cmList)
        wrapList.add(new Wrapper(false,cm));
    system.debug('inmethod'+ cmList);
Public Class Wrapper{
    Public Boolean ischeck{get;set;}
    Public Child__c NCM{get;set;}
    Public Wrapper (Boolean ischeck, Child__c NCM){


     <apex:page controller="MyController">
    <apex:form >
    <apex:pageBlock >    
    <apex:pageBlockSection title="Contacts" rendered="{!flag}">
            <apex:outputLabel value="Name"/>
            <apex:selectlist value="{!name}" size="1" id="values"> 
                <apex:SelectOptions value="{!ContactList}"/>  
                <apex:actionSupport event="onchange" action="{!showrecord}" reRender="con"/>          
            <apex:pageBlockTable value="{!wrapList}" var="v" id="con">
                <apex:column >
                    <apex:inputCheckbox value="{!v.ischeck}"/>
                <apex:column value="{!v.NCM.name}"/>
                <apex:column value="{!v.NCM.Contact__c}"/>
                <apex:column value="{!v.NCM.FieldA__c}"/>
                <apex:column value="{!v.NCM.FieldB__c}"/>
                <apex:column value="{!v.NCM.FieldC__c}"/>                              
        <apex:pageBlockSection rendered="{!NOT(flag)}">

  • I think in my query, I need to add Plural Label (GreatGrandChilds__r). Commented Nov 20, 2014 at 8:38
  • Go to your Child object -- Go to Grand_Child__c lookup field ---> Their you will see a data named Child Relationship Name. Use that for your query. Say if the child relationship name is XYZs then use XYZs__r in your query.
    – snehakem
    Commented Nov 20, 2014 at 9:02
  • @Keith C- I can use two separate queries, but will that work to display all the records in one page block? In that case, do I need to wite one more wrapper class. Could you please help me with the sample code for the same. Commented Nov 20, 2014 at 10:21

1 Answer 1


While you can go up 5 levels in the child to parent direction, you can only go down 1 level in parent to child relationships. See the "Understanding Relationship Query Limitations" section towards the end of the Relationship Queries documentation.

So you will need to use two separate queries. Here is one way to do that (might contain typos):

Map<Id, Child__c> children = new Map<Id, Child__c>([
        Select Id, Name, Contact__c, FieldA__c
        from Child__c
        where Contact__c = :name
Map<Id, List<GrandChild__c>> grandChildren = new Map<Id, List<GrandChild__c>>;
for (GrandChild__c grandChild : [
        Select id, Name, Child__c, FieldB__c,
                (Select id, Name, GrandChild__c, FieldC__c from GreatGrandChild__r)
        from GrandChild__c
        where Child__c in :children.keySet()
        ]) {
    List<GrandChild__c> l = grandChildren.get(grandChild.Child__c);
    if (l == null) {
        l = new List<GrandChild__c>;
        grandChildren.put(grandChild.Child__c, l);
Set<Id> childIds = new Set<Id>();
for(Child__c child : children.values()) {
    List<GrandChild__c> l = grandChildren.get(child.Id);
    if (l = null) {
        l = new List<GrandChild__c>();
    // Wrapper now has extra argument and field, the list of grand children with the
    // great grand children available in each grand child's GreatGrandChild__r field
    wrapList.add(new Wrapper(false, child, l));

You will need to check (or just try a few likely values) the name GreatGrandChild__r; normally this would be a plural so it might be GreatGrandChilds__r or GreatGrandChildren__r - that is a choice the person creating the data model makes.

  • Thanks for the code... Will try this and let you know.... Commented Nov 21, 2014 at 8:17

You must log in to answer this question.

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