Apex Managed Sharing writes directly to the object's __Share table to grant access programmatically.
Setup: define an Apex Sharing Reason (one-time, in the object's Setup -> Sharing Reasons). The reason gets a DeveloperName like Deal_Lawyer__c.
Insert a share:
`apex Account__Share share = new Account__Share(); share.ParentId = accountId; // the record to share share.UserOrGroupId = userId; // the user (or group) to share with share.AccessLevel = 'Read'; // 'Read' or 'Edit' share.RowCause = Schema.Account__Share.RowCause.Deal_Lawyer__c; // your sharing reason
Database.SaveResult sr = Database.insert(share, false); if (!sr.isSuccess()) { for (Database.Error err : sr.getErrors()) { System.debug('Share failed: ' + err.getMessage()); } } `
Important:
- The class must have `without sharing` declared (or be invoked from such a context). Otherwise the share insertion respects the running user's sharing — defeating the purpose.
- For standard objects, only certain ones support Apex Managed Sharing on
__Share. Confirm at the Salesforce documentation. - For custom objects, the OWD must be more restrictive than Public Read/Write (Apex Managed Sharing is meaningless if everyone has access anyway).
Bulk share insert:
apex List<Account__Share> shares = new List<Account__Share>(); for (Map<Id, Id> entry : pairs) { shares.add(new Account__Share( ParentId = entry.parentId, UserOrGroupId = entry.userId, AccessLevel = 'Read', RowCause = Schema.Account__Share.RowCause.Deal_Lawyer__c )); } Database.insert(shares, false);
Recalculation:
When the data driving the sharing changes (e.g., the Deal_Lawyer__c lookup is updated), you must:
- Delete the old share rows:
delete [SELECT Id FROM Account__Share WHERE RowCause = 'Deal_Lawyer__c' AND ParentId = :accountId];. - Re-insert with the new user.
Considerations:
- Apex Managed Sharing rows survive owner changes (unlike Manual Sharing).
- Apex Managed Sharing does NOT participate in the standard "Recalculate Sharing" buttons — you trigger your own recalcs.
- Test thoroughly with
System.runAs(user)to confirm the right users have the right access.
When to use:
- Sharing logic depends on lookups, related-record state, or computations not expressible in Sharing Rules.
- You need access that survives owner changes.
- You need to grant temporary access with deterministic expiry (combined with a scheduled job that deletes stale shares).
