You need to sign in to do that
Don't have an account?

Need help resolving governor limits
I have a trigger that calls a class which establishes record sharing for an object based on the record owner and their role. Essentially I am sharing the record with the owner's role. The org has entirely too many roles that will quickly exceed the number of predefined sharing rules that can be established so this trigger/class solution is necessary across a number of private objects to ensure members of the same role share the same access to records anyone in the same role owns.
My challenge comes in establishing the data set needed to create the sharing in the custom object's sharing object (in this case Team__Share). Specifically, because I am sharing with a Role I need to first grab the record owner, determine their role, and then query the Group object to get the Group Id to pass back into the Team__Share object to set the UserOrGroupId (using the Role Id to set UserOrGroupId causes an error as it is looking for either a User Id or Group Id).
Here is my code for both the trigger and the class with the SOQL that is generating the governor limit execution error commented. This works like a charm if it is just one record being updated/inserted, but obviously fails once testing with larger sets of data.
My challenge comes in establishing the data set needed to create the sharing in the custom object's sharing object (in this case Team__Share). Specifically, because I am sharing with a Role I need to first grab the record owner, determine their role, and then query the Group object to get the Group Id to pass back into the Team__Share object to set the UserOrGroupId (using the Role Id to set UserOrGroupId causes an error as it is looking for either a User Id or Group Id).
Here is my code for both the trigger and the class with the SOQL that is generating the governor limit execution error commented. This works like a charm if it is just one record being updated/inserted, but obviously fails once testing with larger sets of data.
Code:
trigger TeamSharingTrigger on Team__c (after insert, after update) { List<ID> ownerId = new List<ID>(); for (Team__c teamNew1: Trigger.New){ ownerId.add(teamNew1.OwnerId); } Map<ID,User> u = new Map<ID,User>([Select Id, UserRoleId From User where Id in :ownerId]); ID roleId; for (Team__c teamNew2: Trigger.New){ roleId = u.get(teamNew2.OwnerId).UserRoleId; if(roleid != null){ TeamSharingClass.manualShareAll(teamNew2.Id,roleId); } } } public class TeamSharingClass { public static boolean manualShareAll(Id recordId, Id userOrGroupId){ /*Since this is a Role and not a User that I am trying to share with I need to grab the Id of the Group for that role. This is the SOQL that causes the governor limits (executed for each call)*/ ID groupID = [Select g.Id From Group g where g.RelatedId=:userOrGroupId and g.Type='Role'].Id; Team__Share teamShr = new Team__Share(); teamShr.ParentId = recordId; teamShr.UserOrGroupId = groupID; teamShr.AccessLevel = 'Edit'; teamShr.RowCause = Schema.Team__Share.RowCause.Manual; Database.SaveResult sr = Database.insert(teamShr,false); // Process the save results. if(sr.isSuccess()){ // Indicates success return true; } else { // Get first save result error. Database.Error err = sr.getErrors()[0]; // These sharing records are not required and thus an insert exception is acceptable. if(err.getStatusCode() == StatusCode.FIELD_INTEGRITY_EXCEPTION && err.getMessage().contains('AccessLevel')){ // Indicates success. return true; } else{ // Indicates failure. return false; } } } }
My suggestion would be to use maps.
> You are anyway capturing all the Role Id's in a map.
> Create another method that constructs a second map for <User Role Id, Group Id> by passing the KeySet of the map
> Make sure that you call the new method first and put it outside of the for loop. This method will only execute once.
> Once your map is constructed, then use it to get the appropriate groupId
Hope this helps
For anyone else that's interested, below is the code that was used. The Team object is the custom object that's at play and could be replaced with any other object and the below code should still work just fine.
This trigger creates a manual sharing rule for the current owner and shares the record with everyone else in the owner's role (I beefed up the comments too).
and the APEX class....