I want to convert this method to Batch Apex

public void Visibility() {
        Map<Id, List<Id>> accountContactRelationIdsMap = new Map<Id, List<Id>>();

        for (AccountContactRelation accountContactRelation : (List<AccountContactRelation>) Trigger.new) {
            String oldRoles = (Trigger.isUpdate) ? ((AccountContactRelation) Trigger.oldMap.get(accountContactRelation.Id)).Roles : null;
            if (accountContactRelation.Roles != null && accountContactRelation.Roles.contains(labelVisibilitePortail) && (Trigger.isInsert ||
                    (Trigger.isUpdate && (oldRoles == null || !oldRoles.contains(labelVisibilitePortail))))) {
                if (!accountContactRelationIdsMap.containsKey(accountContactRelation.AccountId)) {
                    accountContactRelationIdsMap.put(accountContactRelation.AccountId, new List<Id>());
  • 1
    Hi and welcome to SFSE. Please take a few minutes to read how to ask then edit your question to demonstrate what you have tried and where you are specifically stuck. – Phil W Oct 12 at 16:56
  • 1
    To find out more about writing Batchables, see this trailhead. This should give you enough information to let you convert your code to a batch. – Phil W Oct 12 at 16:57
  • Thanks , i have read that trailhead but i still didn't know how to copy my query and paste it in "Start" method in batch - since my query uses "accountContactRelationIdsMap" Should i declare accountContactRelationIdsMap in start method ? – Farkous Oct 12 at 17:00
  • Simply have your batchable accept the list of objects in the constructor, generate the map and store it as a (private) class attribute. This is then accessible when start is called, and can be used in the query locator returned by start. – Phil W Oct 12 at 17:12
  • BTW, what you added in your comment you should have added into the question itself as I suggested by simply editing it. – Phil W Oct 12 at 17:13

According to your comment, your issue is knowing how to create the map used in the query.

Batchables can contain class attributes like any other Apex class. These values are available for use in the start, execute and finish method implementations, even without implementing Database.Stateful (the latter allows the values of these attributes to be updated in any of these methods otherwise they get their original value each time, set when you called Database.executeBatch).

In this scenario it makes sense for your batchable to receive the records in its constructor, perhaps like:

class MyBatch implements Database.Batchable<FAB_Order_Bill_Price__c> {
    private Map<Id, List<Id>> accountContactRelationIdsMap = new Map<Id, List<Id>>();

    public MyBatch(List<AccountContactRelation> oldRelations, List<AccountContactRelation> relations) {
        // In here do the processing to initialize the accountContactRelationIdsMap
        // using the "oldRelations" and "relations" (which would actually be given the
        // Trigger.old and Trigger.new arrays where you construct the batch and execute
        // it, from within the trigger)

You can now use the map in the query locator returned by the start method basically the same way you already do in your for loop.

As mentioned above, you construct the batch with the trigger old and new data in the trigger, thus:

Database.executeBatch(new MyBatch(Trigger.old, Trigger.new));
| improve this answer | |
  • In this case how to execute my batch ? - i mean which parameters should i use in Database.executeBatch(new MyBatch(?,?)); i will try to copy the first loop and paste it inside the constructor MyBatch – Farkous Oct 12 at 17:30
  • it doesn't work – Farkous Oct 12 at 17:56
  • If you do it right it will work – Phil W Oct 12 at 20:11
  • Please don't think of this as just a copy and paste operation. There is at least a little bit of restructuring you'll need to perform on your code. Between Phil's great answer and Trailhead you should have a pointer in the right direction. – David Reed Oct 12 at 21:30
  • @PhilW , my purpose is how to covert String oldRoles = (Trigger.isUpdate) ? ((AccountContactRelation) Trigger.oldMap.get(accountContactRelation.Id)).Roles : null; with oldRelations & relations parameters in my batch – Farkous Nov 13 at 13:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.