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
    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 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
    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? 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? 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
    Sep 14, 2017 at 23:02

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.