8

I'm working on rewriting a utility method that gives record type ids without using SOQL queries.

I found two ways to do this:

Schema.getGlobalDescribe().get(objName).getDescribe().getRecordTypeInfosByName().get(recTypeName).getRecordTypeId();

and

SObjectType.Account.getRecordTypeInfosByName().get('recTypeName').getRecordTypeId();
SObjectType.Contact.getRecordTypeInfosByName().get('recTypeName').getRecordTypeId();
SObjectType.Opportunity.getRecordTypeInfosByName().get('recTypeName').getRecordTypeId();

The problem with getGlobalDescribe() approach is, it is consuming an average of ~55 milliseconds of Apex CPU time where as the second approach consumes only ~3 milliseconds.

How can I get SObjectType.ObjectName from string 'ObjectName'? I couldn't find a way to achieve this without using the getGlobalDescribe.

I'm hoping to make the second way generic like

SObjectType.ObjectName.getRecordTypeInfosByName().get('recTypeName').getRecordTypeId();
12

Generically speaking, you can do this:

public static Id getRecordTypeIdForObject(String objName, String recTypeName) {
    return ((SObject)Type.forName(objName).newInstance())
        .getSObjectType()
        .getDescribe()
        .getRecordTypeInfosByName()
        .get(recTypeName)
        .getRecordTypeId();
}

You can call it like this:

Id recTypeId = getRecordTypeIdForObject('Account', 'Some Record Type');

This has no error checking, of course, but it should get you started.

Alternatively, assuming you know the type you want in advance:

public static Id getRecordTypeIdForObject(SObjectType objType, String recTypeName) {
    return objType.getDescribe()
        .getRecordTypeInfosByName()
        .get(recTypeName)
        .getRecordTypeId();
}

Which would be called like this:

Id recTypeId = getRecordTypeIdForObject(Account.SObjectType, 'Some Record Type');
  • This is exactly the approach I'm working on. I was stuck at getting sObjectType from string. Now, even that is out of my way. Thank you. – Avinash Jul 24 '17 at 17:40
  • Btw, the average Apex CPU time for this approach is ~4.5 milliseconds. That is less than 10% of the getGlobalDescribe() approach. – Avinash Jul 24 '17 at 17:46
  • 2
    @Avinash Actual performance depends on the number of objects in your org; global describe can get obscenely expensive in large orgs (it takes ~2000 ms in our org, for example). Global describes should definitely be avoided when possible. – sfdcfox Jul 24 '17 at 17:51
  • I believe number of objects shouldn't make a huge difference in this approach as we are looking for a specific object without global describe. – Avinash Jul 24 '17 at 17:57
3

Depending on how you want to use it, the alternative is to sfdcfox's approach is to cache the global describe in a static variable with lazy instantiation e.g.

global class MyUtils {

    private static Map<String, Schema.SObjectType> globalDescribe;

    public static Map<String, Schema.SObjectType> getGlobalDescribe() {
        if(globalDescribe == null) {
            globalDescribe = Schema.getGlobalDescribe();
        }
        return globalDescribe;
    }

    public static Id getRecordTypeIdForObject(String objName, String recTypeName) {
        return getGlobalDescribe()
            .get(objName)
            .getDescribe()
            .getRecordTypeInfosByName()
            .get(recTypeName)
            .getRecordTypeId();
}

This would be slow the first time you call it, but then fast on subsequent calls. If you wanted to take it further, you could cache the describe results as well.

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.