3

I have build an apex tool which analyzes managed Permission Sets, finds specific permissions and creates a custom Permission Set clone without those permissions.

In order to maintain the clones I am deleting all existing children (ObjectPermissions, FieldPermissions, SetupEntityAccess records) from the clone and re-create them from the original Permission Set.

Salesforce throws a DML Exception with following message:

System.DmlException Delete failed. First exception on row 61 with id 1100Y00000dQGnBQAW; first error: FIELD_INTEGRITY_EXCEPTION, Permission Read Namespace__Object1__c depends on permission(s): Read Namespace__Object2__c: []

I checked the Objects and they are in fact in a master detail relationship. Therefore deletion fails because I am deleting the read-access on the parent object before the read-access on the child object.

I am deleting straightforward without any additional checks since my expectation was that Salesforce would manage the order of deletion:

delete [SELECT Id FROM ObjectPermissions WHERE ParentId = :clone.Id];
  1. Does anyone know if this is a bug or intended behavior?
  2. How could I structure a "safe" delete by checking which objects are parents and which are children?
1

Does anyone know if this is a bug or intended behavior?

It's intended behavior. You can't really do things out of order.

How could I structure a "safe" delete by checking which objects are parents and which are children?

I think you should be able to use the following pattern:

ObjectPermissions[] objPerms = [SELECT Id FROM ObjectPermissions WHERE ParentId = :clone.Id], 
    tempPerms = objPerms.clone();
while(!tempPerms.isEmpty()) {
    Database.DeleteResult[] results = Database.delete(tempPerms, false);
    objPerms = tempPerms.clone();
    tempPerms.clear();
    for(Integer index = 0, size = objPerms.size(); index < size; index++) {
        if(!results[index].isSuccess()) {
            tempPerms.add(objPerms[index]);
        }
    }
}

This shouldn't require more than 3 DML operations. What we do is try deleting everything, get any errored records out of the list, try deleting those, etc... Eventually they should all get deleted. This is probably faster than running describes, because you'd have to describe each object, then describe all the fields, finding the appropriate relationship for each, then ordering them correctly... I think it'd be a lot easier to let the system sort it out for you.

  • I altered the code to fit my needs and it works. 3 DML statements is an okay price to pay for that. Thanks for the quick help – Robert Méndez May 3 '17 at 14:35
  • @RobertMéndez You're welcome! Glad I could help. – sfdcfox May 3 '17 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.