Question
I’m encountering an issue with the following trigger method. When attempting to delete an employee record (via UI), the operation fails, and I get this error:
“There’s a problem saving this record. You might not have permission to edit it, or it might have been deleted or archived.”
Here is my trigger:
trigger EmployeeTrigger on Employee__c (before delete, after delete) {
if (Trigger.isAfter && Trigger.isDelete)
EmployeeTriggerHandler.afterDelete(Trigger.old);
}
The trigger calls this method in the handler:
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;
}
}
Observed Behavior:
- The employee record fails to delete.
- The operation ends with the mentioned error.
Can you help me figure out what is causing this issue and how to resolve it?
Answer
The issue with your code is that you are attempting to update Account
records using the Account__r
relationship field directly, but you did not fetch the Id
for these Account
records. Salesforce requires the Id
field to perform DML operations like update
. Without the Id
, the platform cannot determine which Account
records to update, resulting in the error you encountered.
Resolution
You need to modify your afterDelete
method to properly query the Account
records and ensure they include the required Id
field before attempting the update. Below is the corrected version of your handler method:
public class EmployeeTriggerHandler {
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) {
if (record.Account__c != null) {
accounts.put(record.Account__c, new Account(Id = record.Account__c));
}
}
// Get the record counts all at once
recordCounts.putAll([
SELECT Account__c Id, COUNT(Id) recordCount
FROM Employee__c
WHERE Account__c IN :accounts.keySet()
GROUP BY Account__c
]);
// Update the Left_Employee_Count__c for each Account
for (Account account : accounts.values()) {
account.Left_Employee_Count__c = (Integer) recordCounts.get(account.Id)?.get('recordCount') ?? 0;
}
// Update the Account records
update accounts.values();
}
}
Explanation
This solution ensures that you are working with the Id
field for each Account
. The recordCounts
map aggregates the number of Employee__c
records linked to each Account
, grouped by Account__c
. It uses the Safe Navigation Operator (?.)
and Null Coalescing Operator (??)
to avoid null pointer exceptions and provides default values when no matching records exist. This method is efficient and avoids errors related to invalid or missing Id
fields.
Alternative Approach
If you want to avoid querying Account
records separately and instead calculate the employee count on-the-fly, you can use the following simplified method:
public class EmployeeTriggerHandler {
public static void afterDelete(List<Employee__c> oldList) {
Map<Id, Integer> employeeCounts = new Map<Id, Integer>();
// Calculate counts dynamically
for (Employee__c record : oldList) {
if (record.Account__c != null) {
employeeCounts.put(record.Account__c,
employeeCounts.getOrDefault(record.Account__c, 0) + 1);
}
}
List<Account> accountsToUpdate = new List<Account>();
for (Id accountId : employeeCounts.keySet()) {
accountsToUpdate.add(new Account(
Id = accountId,
Left_Employee_Count__c = employeeCounts.get(accountId)
));
}
update accountsToUpdate;
}
}
This approach reduces the number of SOQL queries by counting employee records in Apex itself. However, it may not scale well for a large dataset due to governor limits. For optimal performance, the first approach with SOQL aggregation is recommended.
By using either method, you ensure that the Account
records are properly updated, and the error is resolved.
Real-Time Project-Based Salesforce Training to Kick Start Your Career
Our Salesforce Course provides a thorough understanding of the Salesforce platform, equipping you with the essential skills to excel in the competitive CRM industry. The program focuses on key areas such as Salesforce Admin, Developer, and AI, blending theoretical knowledge with hands-on practical training. Through live projects and assignments, you’ll gain real-world experience and the confidence to tackle complex business challenges using Salesforce solutions. Guided by expert instructors, you’ll develop the technical skills and industry expertise necessary to thrive in the Salesforce environment.
In addition to technical training, our Salesforce training in India offers personalized mentorship, certification exam preparation, and interview coaching to give you a professional edge. You’ll benefit from detailed study resources, hands-on project experience, and dedicated support throughout your learning journey. Upon completing the course, you’ll be fully prepared for certification exams and equipped with the problem-solving skills employers value most. Embark on your Salesforce journey with us today and unlock unlimited career opportunities. Enroll for a Free Demo today!
Leave a Reply
You must be logged in to post a comment.