Look in the code that you have not done any describe call inside the for loop
Schema.DescribeFieldResult F = Account.AccountNumber.getDescribe();
This is an example for field describe .Search for the describe calls in the code and make sure we have out of the for loop.
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_fields_describe.htm
Here is the document of complete list of fielddescribe calls .
There is a limit that in a single context run you can have only 100 fielddescribe calls.This is one of the governor limits of platforms
Here is the class thats causing issue .I see getdescribe inside the for but that may not be issue but please dont call this inside the for loop .Try to bulkify
for(Schema.SObjectField sfield : fieldMap.Values()){
schema.describefieldresult dfield = sfield.getDescribe();
string fname = dfield.getname();
//if (fname.indexOf('pb_') > -1 && fname.indexOf(productName) > -1 )
if (fname == ('pb_Stage_' + productName + '__c') || fname == ('pb_SubStage_' + productName + '__c') ||
fname == ('pb_RecordType_' + productName + '__c') || fname == ('pb_CreateDate_' + productName + '__c') ||
fname == ('pb_Client_' + productName + '__c') || fname == ('pb_CloseDate_' + productName + '__c') ||
fname == ('pb_SubBegin_' + productName + '__c') || fname == ('pb_SubEnd_' + productName + '__c') ||
fname == ('pb_Amount_' + productName + '__c') )
{
if (dfield.isUpdateable())
if (fname == ('pb_Client_' + productName + '__c') )
accObj.put(fname, false);
else
{
accObj.put(fname, null);
}
}
}
return accObj;
As shown above by Andrew Fawcett you may get in map and this should resolve the issue
If you want to execute the same logic for 16 different fields then obviously it would be best to write the algorithm once. And in Salesforce bulking up any database reads and writes is important too. So one trigger that deals with multiple Accounts and handles all 16 fields would be ideal. Restructuring your code now is likely to avoid a lot of future pain.
To execute Apex logic in such a trigger, the get
and put
methods that take the field name string can be used:
List<Xyz__c> updates = new List<Xyz__c>();
Set<String> fields = new Set<String>{'UK_Rep__c', 'FR_Rep__c'', ...};
for (Account a : Trigger.new) {
// Repeat algorithm for each of the 16 fields
for (String field : fields) {
Id repId = (Id) a.get(field);
...
}
}
update updates;
And where you need the query to vary a lot, the query can be created as a string and executed as Dynamic SOQL. (Or sometimes just a where abc in :set
may suffice.)
Also note that the sort of code shown immediately below is generally lethal (= governor limit exception). Fine with 10 Accounts where on average 10x10/2=50 times round the inner loop, but with 1,000 accounts its 1,000x1,000/2=500,000.
for(Account a:accounts){
for(Account old : Accountsold)
{
if (old.id == a.id)
{
Pass Trigger.oldMap
into the class to remove the exponential factor:
for(Account a : accounts) {
Account old : oldAccountsMap.get(a.Id);
Having read through your question and comments I still don't understand why @future is being used. What goes wrong if it is removed?
@Kevin C - The only way StackExchange is allowing me to reply is by editing your Answer. Again I apologize for not using the site as intended and will visit the help center when I have a moment.
First, thank you for your helpful response. To answer your question, the following scenario will occur if @future is removed.
-If John D is the Account Owner and I attempt to add him to one of the Team Role fields on the Account then I receive an error. I do not have the exact error handy, but it is basically saying that I cannot perform the function because I am attempting to give John D lower permissions then what he already has. Due to him being the Account Owner he has 'Full'Access, but my code is trying to give him 'Read/Write'. I would be fine with 'Full Access' but the value is not available in Apex. @future allows the Account Owner to be added as a Team Member when adding him to the custom fields.
Again, thank you for your response. Like I mentioned, I am VERY green when it comes to APEX and really trying to get a handle on it. I will take a closer look at what you provided and see if I can piece it all together.
Best Answer
Salesforce imposes a governor limit that states no more than 50 future calls may be made in a single request. Take a look at the docs. The governor limit is not about 51 records being called/processed inside a future call, it's about the number of future calls in a single request. In your case here you are calling the future method for each user.
You will need to modify your future method to accept a list of these user ids and call once from your UserMasterTrigger. You will end up with something like the following in UserMasterTrigger after modifying FlexeraMemberCreationHandler.FlexeraMemberCreation method: