+ Start a Discussion
SambitNayakSambitNayak 

trigger to count the number of related records

Hi,
I have a requirement to count the number of candidates looking upto a Test Center object. The field "No of Candidates" on the Test Center object should calculate the number of candidates associated.
I wrote an After trigger but it's not updating the field:

trigger candidateTrigger on Candidate__c (after insert, after update, after delete) {
    candidateTriggerHandler.calcNoOfCandidates(Trigger.isDelete ? Trigger.old : Trigger.new);
}

//Handler class
public class candidateTriggerHandler {
    
    public static void calcNoOfCandidates(List<Candidate__c> candList){
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__r.ID != NULL){
            TestCenters.add(can.Test_Center__r.ID);
            }
        }
Map<Id,List<Candidate__c>> mapTestCntrToCand = New Map<Id,List<Candidate__c>>();
        
        for(Test_Center__c tc:[SELECT ID, No_of_Candidates__c , (SELECT Id FROM Candidates__r) 
                               FROM Test_Center__c WHERE Id IN:TestCenters]){
            mapTestCntrToCand.put(tc.Id, tc.Candidates__r);
        }
        
        for(Candidate__c can:candList){
            if(mapTestCntrToCand.containsKey(can.Test_Center__r.ID)){
                Integer noOfCands=0;
                for(Candidate__c c:mapTestCntrToCand.get(can.Test_Center__r.ID)){
                    noOfCands++;
                    system.debug('no of cndts inside for loop: '+ noOfCands);
                }
                can.Test_Center__r.No_of_Candidates__c = noOfCands;
                system.debug('no of cndts outside for loop: '+ noOfCands);
            }
        }
    }
 
Best Answer chosen by SambitNayak
CharuDuttCharuDutt
Hii Sambit
Take Refference from Below Code
trigger NumberOfChild on Candidate__c (After Insert,After Update,After Delete) {
    
    If(trigger.isAfter &&Trigger.isInsert){
        NumberOfChildTriggerHandler.insertMethod(trigger.new);
    }
    If(trigger.isAfter &&Trigger.isUpdate){
        NumberOfChildTriggerHandler.updateMethod(trigger.new,trigger.oldMap);
    }
    If(trigger.isAfter &&Trigger.isDelete){
        NumberOfChildTriggerHandler.deleteMethod(trigger.old);
    }
}




public class NumberOfChildTriggerHandler {
    
    public static Void InsertMethod(list<Candidate__c> lstCon ){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null){
                TestCenters.add(can.Test_Center__c);
            }
        }
        for(Test_Center__c acc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    public static Void UpdateMethod(list<Candidate__c> lstCon,map<Id,Candidate__c>oldmap ){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null && con.Test_Center__c != oldMap.get(con.Id).Test_Center__c){
                setAccIds.add(con.AccountId); 
                setAccIds.add(oldMap.get(con.Id).AccountId);
            }   
        }
        for(Test_Center__cacc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    public static Void deleteMethod(list<Candidate__c> lstCon){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null){
                TestCenters.add(can.Test_Center__c);
            }
        }
        for(Test_Center__c acc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    
    
    
}

Please Mark It As Best Answer If It Helps
Thank You! 

All Answers

SwethaSwetha (Salesforce Developers) 
HI Sambit,
What does this debug line give
 system.debug('no of cndts inside for loop: '+ noOfCands);

Thanks
SambitNayakSambitNayak
Ohh.. Pls ignore that.. I just wanted to debug and see which lines of codes are getting executed.
CharuDuttCharuDutt
Hii Sambit
Take Refference from Below Code
trigger NumberOfChild on Candidate__c (After Insert,After Update,After Delete) {
    
    If(trigger.isAfter &&Trigger.isInsert){
        NumberOfChildTriggerHandler.insertMethod(trigger.new);
    }
    If(trigger.isAfter &&Trigger.isUpdate){
        NumberOfChildTriggerHandler.updateMethod(trigger.new,trigger.oldMap);
    }
    If(trigger.isAfter &&Trigger.isDelete){
        NumberOfChildTriggerHandler.deleteMethod(trigger.old);
    }
}




public class NumberOfChildTriggerHandler {
    
    public static Void InsertMethod(list<Candidate__c> lstCon ){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null){
                TestCenters.add(can.Test_Center__c);
            }
        }
        for(Test_Center__c acc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    public static Void UpdateMethod(list<Candidate__c> lstCon,map<Id,Candidate__c>oldmap ){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null && con.Test_Center__c != oldMap.get(con.Id).Test_Center__c){
                setAccIds.add(con.AccountId); 
                setAccIds.add(oldMap.get(con.Id).AccountId);
            }   
        }
        for(Test_Center__cacc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    public static Void deleteMethod(list<Candidate__c> lstCon){
        List<Test_Center__c> accList=new List<Test_Center__c>();
        
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null){
                TestCenters.add(can.Test_Center__c);
            }
        }
        for(Test_Center__c acc :[Select id,NoOfCandidates__c ,(Select id,name from Candidates__r ) from Test_Center__c where Id in : setAccIds]){
            
            acc.NoOfCandidates__c  = acc.Candidates__r.size();
            
            acclist.add(acc);
        }
        if(acclist.size()>0){
            update accList; 
        }
    }
    
    
    
}

Please Mark It As Best Answer If It Helps
Thank You! 
This was selected as the best answer
SwethaSwetha (Salesforce Developers) 
I see you also posted your ask on https://salesforce.stackexchange.com/a/378088/80089 according to which
for (Candidate__c can : candList) {
    if (can.Test_Center__r.ID != NULL) {
        TestCenters.add(can.Test_Center__r.ID);
    }
}
Test_Center__r.ID will always be null, because related objects are not loaded in Trigger.new/Trigger.old. You can fix this with:
for (Candidate__c can : candList) {
    TestCenters.add(can.Test_Center__c);
}
TestCenters.remove(null); // Remove nulls afterwards

If this information helps, please mark the answer as best. Thank you
SambitNayakSambitNayak
Hi Swetha: Thanks. But still my code is not running.

Hi CharuDutt: That was really helpful. I tried doing the same. Unfortunately, it's still not updating:

    public static void calcNoOfCandidates(List<Candidate__c> candList){
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            //if(can.Test_Center__r.ID != NULL){
            TestCenters.add(can.Test_Center__r.ID);
            //}
        }
        
        List<Test_Center__c> testCntrsToUpdt1 = New List<Test_Center__c>();        
        
        List<Test_Center__c> testCntrsToUpdt = [SELECT ID, No_of_Candidates__c , (SELECT Id FROM Candidates__r) 
                               FROM Test_Center__c WHERE Id IN:TestCenters];

        
        for(Test_Center__c tc:testCntrsToUpdt){
            tc.No_of_Candidates__c = tc.Candidates__r.size();
            testCntrsToUpdt1.add(tc);
        }
        update testCntrsToUpdt1;
CharuDuttCharuDutt
No Sambit
You are Doing Different Read And Compare My Code it succesfully running in my org
 
SambitNayakSambitNayak

Hi CharuDutt....
Same code yet no luck:

 

public static void calcNoOfCandidates(List<Candidate__c> candList, map<Id,Candidate__c>oldmap){
        Set<ID> TestCenters= New Set<ID>();
        for(Candidate__c can:candList){
            if(can.Test_Center__c != null && can.Test_Center__c != oldMap.get(can.Id).Test_Center__c){
            //if(can.Test_Center__r.ID != NULL){
            TestCenters.add(can.Test_Center__r.ID);
            TestCenters.add(oldMap.get(can.id).Test_Center__r.ID);
            }
            //}
        }
        
        List<Test_Center__c> testCntrsToUpdt1 = New List<Test_Center__c>();        
        
        List<Test_Center__c> testCntrsToUpdt = [SELECT ID, No_of_Candidates__c , (SELECT Id FROM Candidates__r) 
                               FROM Test_Center__c WHERE Id IN:TestCenters];

        
        for(Test_Center__c tc:testCntrsToUpdt){
            tc.No_of_Candidates__c = tc.Candidates__r.size();
            testCntrsToUpdt1.add(tc);
        }
        update testCntrsToUpdt1;
        

CharuDuttCharuDutt
Hii Sambit 
Your Are Using 'Test_Center__r.ID' in For Loop If Condition While I'm Using This 'Test_Center__c ' This Is The Deiffrence See It Now
SambitNayakSambitNayak

Thanks CharuDutt...

It really works now!!