Apex扩展类更新关联字段报错:INVALID_ID_FIELD求助
Let’s walk through what’s causing this error and how to fix it properly:
Why You’re Seeing the Error
Your current ContactExt class uses controller.getRecord(), which in a mass edit context (with recordSetVar) returns an empty Contact template (no ID)—not the actual selected contacts you’re editing. When you call update record; on this empty record, Salesforce throws the "record id cannot be empty" error because you can’t update a record without an ID.
Additionally, even if you fixed the ID issue, editing a.Account.Organization_Size__c directly in Visualforce won’t automatically update the Account record—you need to explicitly handle that in your Apex code, since the Contact StandardController only manages Contact records, not their related Accounts.
Step 1: Update the Apex Extension Class
Replace your ContactExt class with this version, which handles mass selected records and properly updates associated Accounts:
public class ContactExt { private ApexPages.StandardSetController setController; private Map<Id, Account> accountsToUpdate = new Map<Id, Account>(); public ContactExt(ApexPages.StandardSetController controller) { setController = controller; // Load all selected records if none are pre-selected (for initial page load) if(setController.getSelected() == null || setController.getSelected().isEmpty()){ setController.setPageSize(setController.getResultSize()); } } public PageReference save(){ try{ // Get all selected Contact records from the mass edit list List<Contact> selectedContacts = (List<Contact>)setController.getSelected(); // Collect and deduplicate Accounts that need their Organization_Size__c updated for(Contact con : selectedContacts){ if(con.AccountId != null && con.Account != null && con.Account.Organization_Size__c != null){ if(accountsToUpdate.containsKey(con.AccountId)){ // Use the latest value entered for the Account (handles multiple Contacts linked to same Account) accountsToUpdate.get(con.AccountId).Organization_Size__c = con.Account.Organization_Size__c; } else { accountsToUpdate.put(con.AccountId, new Account( Id = con.AccountId, Organization_Size__c = con.Account.Organization_Size__c )); } } } // Update all selected Contacts first update selectedContacts; // Update the associated Accounts if there are any changes if(!accountsToUpdate.isEmpty()){ update accountsToUpdate.values(); } ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM, 'Contacts and their associated Accounts updated successfully!')); return null; } catch(DmlException e){ ApexPages.addMessages(e); return null; } } }
Step 2: Clean Up the Visualforce Page
You have duplicate "Organisation Size" columns in your page table—remove the extra one to avoid confusion, and keep only the one bound to the Account field. Here’s the updated pageBlockTable section:
<apex:pageBlockTable value="{!selected}" var="a" id="table"> <apex:column headerValue="Name"> <apex:inputField value="{!a.Name}"/> </apex:column> <apex:column headerValue="Phone"> <support:clickToDial number="{!a.Phone}" entityId="{!a.Id}"/> </apex:column> <apex:column headerValue="Mobile Phone"> <apex:inputField value="{!a.MobilePhone}"/> </apex:column> <apex:column headerValue="Email"> <apex:inputField value="{!a.Email}"/> </apex:column> <apex:column headerValue="Title"> <apex:inputField value="{!a.Title}"/> </apex:column> <apex:column headerValue="Account"> <apex:inputField value="{!a.AccountId}"/> </apex:column> <apex:column headerValue="Description"> <apex:inputField value="{!a.Description}"/> </apex:column> <apex:column headerValue="Organisation Size (Account)"> <apex:inputField value="{!a.Account.Organization_Size__c}"/> </apex:column> </apex:pageBlockTable>
Key Fixes Explained
- Mass Record Handling: We now use
setController.getSelected()to get all the actual contacts you’re editing, not an empty template. - Account Update Logic: We collect all unique Accounts that need their
Organization_Size__cupdated, deduplicate them, and run a separate DML update for those Accounts. - Error Handling: Added a try-catch block to display meaningful error messages on the page instead of crashing silently.
- Clean UI: Removed duplicate columns to avoid user confusion.
Important Notes
- Make sure the user running this page has Edit permissions on the Account object and the
Organization_Size__cfield. - If multiple Contacts link to the same Account, the last entered
Organization_Size__cvalue will be saved (this is standard mass edit behavior, but you can adjust the logic if needed). - Keep Salesforce’s DML limits in mind—this code handles up to 1000 records (the standard limit) in one save.
内容的提问来源于stack exchange,提问作者Werner Adewole

