Deleting Records¶
Learn how to delete Salesforce records.
Using delete()¶
Delete a record instance:
const account = await Account.find('001xx000003DGbQAAW');
if (account) {
await account.delete();
console.log('Account deleted');
// The instance is now marked as deleted
console.log(account.isDeleted()); // true
}
Using destroy()¶
Delete a record by ID without fetching it:
// More efficient - no fetch required
await Account.destroy('001xx000003DGbQAAW');
console.log('Account deleted');
Bulk Delete¶
Delete multiple records:
const accounts = await Account
.select(x => ({ Id: x.Id }))
.where(x => x.Industry === 'Obsolete')
.get();
await Promise.all(
accounts.map(account => account.delete())
);
console.log(`Deleted ${accounts.length} accounts`);
Delete by IDs¶
Delete records using their IDs:
const idsToDelete = ['001xxx', '001yyy', '001zzz'];
await Promise.all(
idsToDelete.map(id => Account.destroy(id))
);
Deleted Record Behavior¶
Once deleted, the instance is marked and cannot be modified:
const account = await Account.find('001xxx');
await account.delete();
// These will throw errors:
try {
await account.save();
} catch (error) {
console.error(error.message); // "Cannot save a deleted record"
}
try {
await account.update({ Name: 'New' });
} catch (error) {
console.error(error.message); // "Cannot update a deleted record"
}
try {
account.Name = 'Test';
} catch (error) {
console.error(error.message); // "Cannot modify a deleted record"
}
// Data is still accessible for reference
console.log(account.Name); // Still works
console.log(account.isDeleted()); // true
With Observers¶
Observers can intercept delete operations:
class AccountObserver implements Observer<Account> {
async beforeDelete(instance: Account): Promise<void> {
// Prevent deletion based on conditions
if (instance.get('IsActive')) {
throw new Error('Cannot delete active accounts');
}
console.log(`About to delete account: ${instance.Id}`);
}
async afterDelete(instance: Account): Promise<void> {
// Audit logging
console.log(`Account ${instance.getId()} deleted at ${new Date()}`);
// Clean up related data
await cleanupRelatedRecords(instance.getId());
}
}
Account.observe(new AccountObserver());
// Triggers hooks
await account.delete();
Handling Errors¶
try {
await account.delete();
} catch (error) {
console.error('Delete failed:', error.message);
// Handle Salesforce errors (e.g., record locked, permissions)
}
Soft Delete Pattern¶
Implement soft deletes using a custom field:
// Instead of deleting, mark as inactive
const account = await Account.find('001xxx');
if (account) {
account.IsDeleted__c = true;
account.DeletedDate__c = new Date().toISOString();
await account.save();
}
// Query only active records
const activeAccounts = await Account
.select(x => ({ Id: x.Id, Name: x.Name }))
.where(x => x.IsDeleted__c === false)
.get();
Conditional Delete¶
Delete based on criteria:
const account = await Account.find('001xxx');
if (account) {
// Only delete if conditions are met
if (account.AnnualRevenue === 0 && account.NumberOfEmployees === 0) {
await account.delete();
console.log('Inactive account deleted');
} else {
console.log('Account is still active');
}
}
Cascade Deletes¶
Salesforce handles cascade deletes automatically for master-detail relationships. For lookup relationships, you may need to handle related records:
class AccountObserver implements Observer<Account> {
async beforeDelete(instance: Account): Promise<void> {
// Delete related custom records
const relatedRecords = await CustomObject
.select(x => ({ Id: x.Id }))
.where(x => x.AccountId__c === instance.Id)
.get();
await Promise.all(
relatedRecords.map(record => record.delete())
);
}
}
delete() vs destroy()¶
delete()¶
- Requires an instance
- Triggers observers
- Marks instance as deleted
- More overhead
destroy()¶
- Static method
- Takes an ID parameter
- Triggers observers
- More efficient (no fetch required)
Best Practices¶
- Validate before delete - Use observers for validation
- Use destroy() for efficiency - When you only have the ID
- Handle errors - Wrap in try/catch
- Clean up related data - Use observers for cleanup
- Consider soft deletes - For records that need audit trails
- Check permissions - Ensure user has delete access
Next Steps¶
- Creating Records - Insert new records
- Updating Records - Modify records
- Observers - Lifecycle hooks