1

I'm setting an an AEP Selector which needs to implement the following:

[select ParentId from SetupEntityAccess where SetupEntityId in
   (select Id from CustomPermission where DeveloperName = :name)]

However, I'm struggling to wrap my head around how this could be done with out performing two separate queries.

Does anyone know how to do this with out executing a query first to get the Ids of CustomPermission, then performing another query passing the Ids in?

Here's the selector class missing the implementation for this query:

public inherited sharing class SetupEntityAccessesSelector extends fflib_SObjectSelector implements ISetupEntityAccessesSelector
{
    public static ISetupEntityAccessesSelector newInstance()
    {
        return (ISetupEntityAccessesSelector) Application.Selector.newInstance(SetupEntityAccess.SObjectType);
    }

    public List<Schema.SObjectField> getSObjectFieldList()
    {
        return new List<Schema.SObjectField> {
                SetupEntityAccess.Id,
                SetupEntityAccess.ParentId
        };
    }

    public Schema.SObjectType getSObjectType()
    {
        return SetupEntityAccess.SObjectType;
    }

    public List<SetupEntityAccess> selectByCustomPermission(String name)
    {
        fflib_QueryFactory setupEntityAccessQueryFactory = newQueryFactory();
        // Somehow do this:
        // [select ParentId from SetupEntityAccess where SetupEntityId in (select Id from CustomPermission where DeveloperName = :name)]
        return Database.query(setupEntityAccessQueryFactory.toSOQL());
    }
}

Thank you.

3
  • This article should help you: quirkyapex.com/2016/08/18/fflib-selector-layer
    – Badbaxx
    Jun 3, 2023 at 11:39
  • Thanks @Badbaxx however I don't see any mention of using in (soql query) in these examples. Am I somehow overlooking it? Jun 5, 2023 at 16:59
  • 1
    selector methods can implement straight static SOQL or dynamic SOQL. You don't have to use queryFactories. Selectors should be thought of as reusable, mockable wrappers around SOQL. Query factories are there to reuse the list of fields over and over again without having to think about it each time.
    – cropredy
    Jun 7, 2023 at 17:42

2 Answers 2

2

Look at the QueryFactory class. The only way to set conditions in fflib is to pass a String. There is absolutely no way doing that with fflib.

The issue you have is an architectural one. What you want to do doesn't respect the UoW design pattern at all.

You want to:

  • create a Selector for your permissions with a method that queries them by name
  • use the getRecordsId() method that your Permission domain inherits from the magical fflib_SObjects class to get your permissions Ids
  • implement a queryByPermissionId method for your selector that will be responsible of converting your permissions Id set in a condition
  • and then hence your use case involves already 2 selectors and a domain, it needs to be glued into a Service method, ideally one that makes senses business value wise. By convention service methods should take Set of Id as parameters as well.

I'm pretty sure that with all this in mind you'll be able to rethink your use case "properly". Those paradigms are challenging and we all tried the "easy" approach first so don't worry.

1

As it turns out, there is no way to perform this operation in a single query utilizing QueryFactory. Therefore I decided to simply use the SOQL in the method instead:

public List<SetupEntityAccess> selectByCustomPermission(String name)
{
    return [select ParentId from SetupEntityAccess where SetupEntityId in (select Id from CustomPermission where DeveloperName = :name)]
}

This has the following advantages:

  1. Only uses one SOQL query instead of two.
  2. Reduces complexity.
  3. Still adheres to the separation of concerns principle, and arguably still implements the selector pattern.

According to another answer:

What you want to do doesn't respect the UoW design pattern at all.

I'm don't see how the UoW pattern is relevant to this question or scenario at all, since I'm performing a select, not an insert, update, or delete, which is the domain of the UoW pattern.

You must log in to answer this question.

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