function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mike_M_2Mike_M_2 

SObject row was retrieved via SOQL without querying the requested field: Opportunity.Name

I've read everything I can on this error (subject line) but I think I AM querying the request field, so I need help. I have a custom object as the detail side of a Master-Detail relationship with Opportunity as the parent. II'm building a very simple Visualforce page which is placed on the Opportunity screen.
<apex:page standardController="Opportunity" extensions="opportunityListYoY"  sidebar="false" showHeader="false">
    <apex:form >
        <apex:pageBlock >
            <apex:pageMessages />
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!quicksave}"/>
            </apex:pageBlockButtons>
            
            <apex:pageBlockTable value="{!amounts}" var="x" id="list">
            
                <apex:column headerValue="Type">
                    <apex:inputField value="{!x.type__c}"/>
                </apex:column>
                 
                <apex:column headerValue="Opp">
                    <apex:inputField value="{!x.MonthlyRevenueAmounts__r.name}"/>
                </apex:column>
                
                <apex:column headerValue="Amount">
                    <apex:inputField value="{!x.Dollar_Amount__c}"/>
                </apex:column>

            </apex:pageBlockTable> 
        </apex:pageBlock>
    </apex:form>
</apex:page>
The controller extension is:
public class opportunityListYoY {

    private final Opportunity opp;

    public opportunityListYoY(ApexPages.StandardController stdController) {
        this.opp = (Opportunity)stdController.getRecord();
    }

    public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                    [SELECT MonthlyRevenueAmounts__r.name , Dollar_Amount__c, type__c, Fiscal_Date__c, Show_On_Report__c 
                       FROM Revenue_Amount__c
                //    WHERE MonthlyRevenueAmounts__r.name = 'Mikes Opp'  ]));  <--- THIS LINE WORKS FINE
                      WHERE MonthlyRevenueAmounts__r.name = :opp.Name  ]));  <-- this line rasises the error
                    
            }
            return setCon;
        }
        set;
    }

    public List<Revenue_Amount__c> getAmounts() {
        return (List<Revenue_Amount__c>) setCon.getRecords();
    }
}
TIA,
Mike

 
Best Answer chosen by Mike_M_2
NehaDabas16NehaDabas16
Hi Mike,

By default, this.opp = (Opportunity)stdController.getRecord(); , the getRecord() method fetches only the fields which are referenced  in VF page. And as you are not referencing opp.Name anywhere in the page, it is not querried and thus it is throwing exception. 

You can work around this in 2 ways,
  1. Make your opportunity object public and create a hidden field on VF page which refers to opp.Name and for which rendered is set to false.
  2. Make a SOQL query to fetch opportunity name in your method.
You can refer getRecord() definition in followed link for more details : https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_pages_standardcontroller.htm 

Please like and mark resolved, if this helps.

All Answers

Mike_M_2Mike_M_2
To answer my own question, This line
public opportunityListYoY(ApexPages.StandardController stdController) {
        this.opp = (Opportunity)stdController.getRecord();
    }

does not return the full opportunity record, just the id and the record type. In order to get the name I had to add some code so now it looks like 
public class opportunityListYoY {

    private final Opportunity opp;
    private final Opportunity opp2;

    public opportunityListYoY(ApexPages.StandardController stdController) {
        this.opp = (Opportunity)stdController.getRecord();

        opp2 = [ SELECT Id, Name  FROM Opportunity WHERE Id =
            :ApexPages.currentPage().getParameters().get('id') ];
    }

    public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {
                
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                    [SELECT MonthlyRevenueAmounts__r.name , Dollar_Amount__c, type__c, Fiscal_Date__c, Show_On_Report__c 
                       FROM Revenue_Amount__c
                   WHERE MonthlyRevenueAmounts__r.name = :opp2.Name  ]));

            }
            return setCon;
        }
        set;
    }

    public List<Revenue_Amount__c> getAmounts() {
        return (List<Revenue_Amount__c>) setCon.getRecords();
    }
}
NehaDabas16NehaDabas16
Hi Mike,

By default, this.opp = (Opportunity)stdController.getRecord(); , the getRecord() method fetches only the fields which are referenced  in VF page. And as you are not referencing opp.Name anywhere in the page, it is not querried and thus it is throwing exception. 

You can work around this in 2 ways,
  1. Make your opportunity object public and create a hidden field on VF page which refers to opp.Name and for which rendered is set to false.
  2. Make a SOQL query to fetch opportunity name in your method.
You can refer getRecord() definition in followed link for more details : https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_pages_standardcontroller.htm 

Please like and mark resolved, if this helps.
This was selected as the best answer
Mike_M_2Mike_M_2
Neha, that makes sense now. No need for my workaround as posted in my previous post. THANKS!