2

We have been using FF library for Separation of Concerns framework and it is working great. We need to add subquery to it, but running into issues. Example I am following is from this article: https://quirkyapex.com/2016/08/18/fflib-selector-layer/

public class OpportunityLineItemsSelector extends fflib_SObjectSelector {

   public Schema.SObjectType getSObjectType(){
      return OpportunityLineItem.sObjectType;
   }

   public override List<Schema.SObjectField> getSObjectFieldList(){
      return new List<Schema.SObjectField> {
         OpportunityLineItem.Id,
         OpportunityLineItem.Quantity,
         OpportunityLineItem.SalesPrice
      };
   }

}

public class OpportunitiesSelector extends fflib_SObjectSelector {

   public Schema.SObjectType getSObjectType(){
      return Opportunity.sObjectType;
   }

   public override List<Schema.SObjectField> getSObjectFieldList(){
      return new List<Schema.SObjectField> {
         Opportunity.Id,
         Opportunity.StageName
      };
   }

   public List<Opportunity> selectByIdWithLineItems(Set<Id> recordIds){
      fflib_QueryFactory query = newQueryFactory();
      query.setCondition('Id IN :recordIds');
      query.addQueryFactorySubselect( 
         new OpportunityLineItemsSelector().newQueryFactory() 
      );
      return (List<Opportunity>) Database.query( query.toSOQL() );
   }

}

I get compile error:

Method does not exist or incorrect signature: void addQueryFactorySubselect(fflib_QueryFactory) from the type fflib_QueryFactory at line 17 column 13

Below method does exist in "fflib_SObjectSelector" class

global fflib_QueryFactory addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory)
{
    return addQueryFactorySubselect(parentQueryFactory, true);
}

What am I missing here?

4
  • Is ev_QueryFactory is a subtype of fflib__QueryFactory? It seems that your user-defined type ev_QueryFactory is not valid type for this method addQueryFactorySubselect(fflib__QueryFactory parentQueryFactory)
    – Eduard
    Commented Sep 8, 2017 at 18:00
  • Hi Eduard, we have replaced "fflib" with "ev". So you can ignore that, I have edited the question. The issue still persists , thank you for your time Commented Sep 8, 2017 at 18:40
  • Why does your code above have both single and double underscores in the name of the type? (fflib_QueryFactory vs fflib__QueryFactory) The signature in your ev_SObjectSelector class doesn't match the type you're showing in the selectByIdWithLineItems method.
    – Mark Pond
    Commented Sep 8, 2017 at 19:29
  • hi Mark, it was typo from replacing "ev_" with "fflib_" I have corrected that in question above. Why would it complain about method signature? Commented Sep 8, 2017 at 21:41

1 Answer 1

2

Your method

public List<Opportunity> selectByIdWithLineItems(Set<Id> recordIds){
      fflib_QueryFactory query = newQueryFactory();
      query.setCondition('Id IN :recordIds');
      query.addQueryFactorySubselect( 
         new OpportunityLineItemsSelector().newQueryFactory() 
      );
      return (List<Opportunity>) Database.query( query.toSOQL() );
   }

Option 1: should look like this to include subqueries (gives you option to decide on subquery fields)

public List<Opportunity> selectByIdWithLineItems(Set<Id> recordIds){
      if (recordIds.isEmpty()) return new list<Opportunity>(); // avoid burning SOQL
      fflib_QueryFactory oQf = newQueryFactory()
                                .setCondition('Id IN :recordIds');

      fflib_QueryFactory oliQueryFactory = oQF.subselectQuery('OpportunityLineItems')
                .selectFields(new OpportunityLineItemsSelector().getSobjectFieldList()); 

      return Database.query(oQf.toSOQL() );
   }

Option 2: or should should look like this (see example in fflib github) - unconditionally get all subquery fields

public List<Opportunity> selectByIdWithLineItems(Set<Id> recordIds){
      if (recordIds.isEmpty()) return new list<Opportunity>(); // avoid burning SOQL
      fflib_QueryFactory oQF = newQueryFactory()
                                .setCondition('Id IN :recordIds');

      fflib_QueryFactory oliQF = new OpportunityLineItemsSelector().
            addQueryFactorySubselect(oQF,'OpportunityLineItems');

      return Database.query(oQF.toSOQL() );
   }
2
  • Thank you cropredy, I like the option 1. To add Ordering or Where clause, I can do fflib_QueryFactory oliQueryFactory = oQF.subselectQuery('OpportunityLineItems') .selectFields(new OpportunityLineItemsSelector().getSobjectFieldList()). .setCondition(whereClause) .addOrdering(o); This is all good. But instead of me defining that here, I would like user to pass me fflib_QueryFactory for sub query which I can then add to oQF. Any idea how I can do that? Commented Sep 14, 2017 at 13:42
  • Your exact issue - I'm not sure, never did that and Selector pattern design doesn't call for dynamically passing in queryFactories to aid in building up a selector. I'd post your requirement as an Issue in the fflib GitHub.
    – cropredy
    Commented Sep 14, 2017 at 23:02

You must log in to answer this question.

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