I'm writing custom history tracking code, tracking needs to be done for more than 50 fields

All working fine, but instead of record type name , I'm getting record type id, and the same is happening for Account & Owner. Getting id not but not able to get name.

Thinking a lot but not able to find the solution. Here is my code snippet:

// map_Allfields = all fields of object say contact 

//loop through all records 
For (Contact c : Trigger.new) 
   // loop through fields of contact
   for (Schema.SObjectField SobjectFld: map_Allfields.values()) 
          Schema.DescribeFieldResult describeResult = SobjectFld.getDescribe();

            //If field is of type recordtype, get name instead ID
            If (describeResult.getName() == 'RecordTypeId') 
                  String recordtypeID =  c.get(describeResult.getName()) 
                 //get name of Record Type of current record. how ?
            system.debug('FieldValue='+ c.recordtype.Name);// not working

            If (describeResult.getName() == 'OwnerID') 
              String ownerID =  c.get(describeResult.getName())
              // get Owner name of this of current record
               system.debug('FieldValue='+ c.Owner.Name);// not working

            If (describeResult.getName() == 'AccountID') 
             String AccountID=  c.get(describeResult.getName())
             // get Account Name of current record
             system.debug('FieldValue='+ c.Account.Name);// not working


1 Answer 1


When working in a trigger values for all fields are loaded, but not for related objects.

With the lookups to account, record type and owner (user) you get the IDs because they've been loaded as the field values, but account name, record type and owner name aren't loaded as they are fields on the related records, not on the records being worked.

To get the names you'll have to collect the IDs for each type (probably in a map) and then query for them, so for accounts you'd do something like this:

Map<Id, Account> accounts = new Map<Id, Account>();

If (describeResult.getName() == 'AccountID') 
    String AccountID = c.get(describeResult.getName())
    accounts.put(AccountID, null);

/* Snip */

for(Account a : [select Id, Name, OtherFields from Account where Id in : accounts.keySet()])
    accounts.put(a.Id, a.Name);

For your use case you'd then need to loop over the lookup fields once more to get the values.

Something To Consider

Although for history tracking purposes having the names would be easier to read, tracking the changes to the IDs would be just as valid (in fact it would potentially be the only real way of tracking history as pointed out by @ManSpan below). Assuming that you're storing this history information in a custom object, you could always a custom page that displays records take care of looking up names for IDs.

  • 1
    Unless its a business requirement to keep track of the Names at the time of update, I would also go for lookups. Because imagine that someone changes the Account name after the contact update, your history object will still contain the old name. However if you use Lookups, names will be automatically updated to their current values
    – ManSpan
    Jun 30, 2014 at 8:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .