I have a trigger (simplified sample code below) that is using field describes to determine what fields were changed to conditionally update some other field on the same record. The problem is that you are limited to 100 field describes so any mass update will break this trigger.
How can I get around this? Future methods won't work since they can only take primitive parameters and I need to know the values of any potentially changed fields. Enumerating every possible changed field is not feasible.
trigger ObjectBefore on Object__c (before update) {
Set<String> fieldsToIgnore = new Set<String> {'custom_field1__c',
'custom_field2__c',
'custom_field3__c'};
for (Object__c obj : Trigger.new) {
if (Trigger.isUpdate) {
Object__c old = Trigger.oldMap.get(obj.Id);
Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.Object__c.fields.getMap();
for (String fieldName : fieldMap.keyset()) {
if(!fieldsToIgnore.contains(fieldName.toLowerCase()) && old.get(fieldName) != obj.get(fieldName)) {
obj.Custom_Field4__c = 'some value';
System.Debug('**** Field Changed: ' + fieldName);
}
}
}
}
}
Attribution to: DerekLansing
Possible Suggestion/Solution #1
You need to maintain schema in class as static collection(Map) and then refer that class in trigger.
Refer following code -
// Key : SobjectAPIName For ex. Account
// Value : Map<String, Schema.SObjectField>, field map (k:fieldname, v:Schema.Sobjectfield)
private static final Map<String, Map<String, Schema.SObjectField>> FieldMapCache = new Map<String, Map<String, Schema.SObjectField>>();
private static final Map<String, Schema.SObjectType> GlobalDescribe = Schema.getGlobalDescribe();
// Key: sobject.field
// Value: first picklist value
private static final Map<String, String> DefaultPicklistValue = new Map<String, String>();
// can't map by Schema.sObjectType, use object name String instead
public static map<String, set<String>> ExcludedFields = new map<String, set<String>>{
'All' => new set<String>{'OwnerId', 'LastModifiedById', 'CreatedById', 'LastModifiedDate', 'CreatedDate'},
'Account' => new set<String>{'FirstName', 'LastName'}
};
Complete class with code you can reuse - https://raw.github.com/mbotos/SmartFactory-for-Force.com/master/src/classes/SmartFactory.cls
Thanks to awesome work done by SmartFactory for Force.com project Team
http://developer.force.com/projectpage?id=a063000000Db0CSAAZ
Attribution to: Prafulla Patil
Possible Suggestion/Solution #2
Doh. I figured it out. I was being silly and including the describe operation inside my iteration loop. I only need to do that once since the object schema isn't going to change between objects. Fixed code below:
trigger ObjectBefore on Object__c (before update) {
Set<String> fieldsToIgnore = new Set<String> {'custom_field1__c',
'custom_field2__c',
'custom_field3__c'};
Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.Object__c.fields.getMap();
for (Object__c obj : Trigger.new) {
if (Trigger.isUpdate) {
Object__c old = Trigger.oldMap.get(obj.Id);
for (String fieldName : fieldMap.keyset()) {
if(!fieldsToIgnore.contains(fieldName.toLowerCase()) && old.get(fieldName) != obj.get(fieldName)) {
obj.Custom_Field4__c = 'some value';
System.Debug('**** Field Changed: ' + fieldName);
}
}
}
}
}
Attribution to: DerekLansing
Possible Suggestion/Solution #3
Had a chance to look at that.I feel best approach would be using custom settings and the Dynamic DML instead of schema describe calls.In custom settings we can store Tokens of the fields .Schema Describe are heavy calls .
Attribution to: Mohith Shrivastava
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/1870