Salesforce Technical Questions and answers

Why Does My Trigger Fail on Record Deletion?

Spread the love

Question

Can you help me identify the issue with the following trigger and method? I’m encountering an error when trying to delete an employee record via the UI. The error message displayed is: “There’s a problem saving this record. You might not have permission to edit it, or it might have been deleted or archived. Contact your administrator for help.”

Here’s the trigger:

trigger EmployeeTrigger on Employee__c (before delete, after delete) {   
    if (Trigger.isAfter && Trigger.isDelete)
        EmployeeTriggerHandler.afterDelete(Trigger.old);
}

And here’s the method being called:

public class EmployeeTriggerHandler {
    
    // After employee is deleted, update 'Left Employee Count' on Account
    public static void afterDelete(List<Employee__c> oldList) {
        List<Account> accToUpdate = new List<Account>();
        for (Employee__c e : oldList) {
            if (e.Account__c != null) {
                e.Account__r.Left_Employee_Count__c = [SELECT count() FROM Employee__c WHERE Account__c =: e.Account__c];
                accToUpdate.add(e.Account__r);
            }
        }
        update accToUpdate;
    }
}
  • When I delete an employee record (via UI), it ends with the error mentioned above. The record is still being deleted, but it seems the process isn’t completing correctly.

Answer

The main issue with the original trigger lies in the fact that the trigger is trying to call update without ensuring that the Account records are properly populated with the required Id values. In Salesforce, you cannot update a record unless its Id is explicitly provided.

Here is the corrected version of the afterDelete method:

public class EmployeeTriggerHandler {    
    // After employee is deleted, update 'Left Employee Count' on Account
    public static void afterDelete(List<Employee__c> oldList) {
        // Accounts to update, deduplicated by Id
        Map<Id, Account> accounts = new Map<Id, Account>();
        // Record counts
        Map<Id, AggregateResult> recordCounts = new Map<Id, AggregateResult>();
        // Aggregate the account Id values
        for(Employee__c record: oldList) {
            accounts.put(record.Account__c, new Account(Id=record.Account__c));
        }
        // Ignore null values (more efficient than if)
        accounts.remove(null);
        // Get the record counts all at once
        recordCounts.putAll([SELECT Account__c Id, COUNT(Id) recordCount FROM Employee__c WHERE Account__c = :accounts.keySet() GROUP BY Account__c]);
        // For each account, get the record count, or default to 0 (optional)
        for(Account record: accounts.values()) {
            record.Left_Employee_Count__c = (Integer) recordCounts.get(record.Id)?.get('recordCount') ?? 0;
        }
        // Update the records
        update accounts.values();
    }
}

Explanation of Changes:

  1. Properly Handling Account Ids: Instead of directly using the Account__r relationship, we store the account Id in a map and ensure we create Account objects with the Id for each related account.
  2. Avoiding Null Pointer Issues: The use of the Safe Navigation Operator (?.) ensures that the code does not throw a null pointer exception when there are no related employee records. The null coalescing operator (??) provides a default value of 0 when there are no records.
  3. Optimizing the Query: By using AggregateResult in the query, the account’s employee count is retrieved in a single query, which reduces the number of database calls and improves performance.

By applying these changes, you ensure that the Account records are properly updated with the correct Id and the employee count is updated accurately without causing errors during deletion.

Summing Up

The issue with the trigger arises because the handler method attempts to update Account records without explicitly setting their Id values, which is required for updates in Salesforce. The corrected method uses a Map<Id, Account> to ensure all Account records have valid Ids, retrieves the employee counts using a single SOQL query with AggregateResult, and updates the Account records safely using the Safe Navigation (?.) and Null Coalescing (??) operators to handle null values. These changes resolve the error and ensure smooth record deletion and account updates.

Kick Start Your Journey with Real-Time Project-Based Salesforce Learning

Our Salesforce Course is designed to provide an in-depth understanding of the Salesforce platform, equipping you with the essential skills to thrive in the CRM sector. The curriculum features key modules such as Salesforce Admin, Developer, and AI, seamlessly combining theoretical concepts with hands-on learning. Through practical exercises and real-world project involvement, you’ll gain the expertise required to solve complex business challenges using Salesforce solutions. Our skilled instructors ensure you gain the technical knowledge and industry insights to excel in the Salesforce ecosystem.

In addition to building technical skills, our Salesforce training in Chennai offers personalized mentoring, exam preparation, and interview coaching to enhance your career potential. Participants will benefit from comprehensive study materials, hands-on project experience, and one-on-one guidance throughout the course. Upon completing the program, you’ll be well-prepared for certification exams and equipped with the problem-solving skills and practical experience that employers are looking for. Take the first step towards your Salesforce career with us and open doors to endless opportunities. Sign up for a Free Demo!

Open Chat
1
Dear Sir/Madam
How can I help you?