13

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();

2 Answers 2

20

Generically speaking, you can do this:

public static Id getRecordTypeIdForObject(String objName, String recTypeName) {
    return ((SObject)Type.forName('Schema', 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');
10
  • 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
    Commented Jul 24, 2017 at 17:40
  • 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
    Commented Jul 24, 2017 at 17:51
  • 1
    Yes, I just saw that! Better is: Type.forName('Schema', objName). I'll make the change in line. Commented Oct 16, 2020 at 20:10
  • 1
    docs for future reference: "When referencing the Location object in your Apex code, always use Schema.Location instead of Location to prevent confusion with the standard Location compound field" Commented Oct 16, 2020 at 20:12
  • 1
    @CharlesKoppelman Yeah, I should have thought of that, lol. Still, nice to know we finally have a Location field. That's been a Salesforce Idea for ages. Thanks for the follow up on this, I have close to 10k answers, it's hard to keep them all up to date.
    – sfdcfox
    Commented Oct 16, 2020 at 20:13
7

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.

2
  • 1
    That's the approach I tend to take.
    – Adrian Larson
    Commented Jul 25, 2017 at 17:26
  • 1
    +1 But it's still dangerous in some orgs. I remember one org I had where it took ~5,000ms to call Schema.globalDescribe. Losing have your CPU time to a single method call really limits your options.
    – sfdcfox
    Commented Oct 16, 2020 at 20:06

You must log in to answer this question.

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