8

Is there a more efficient way to determine the name field of an sobject other than iterating through all the fields obtained via DescribeSOBjectResult?

Often, the name field is simply Name but in some occasions with standard objects it is not. For example, Case's name field is CaseNumber.

Here is the apex method I'm using, but seems inefficient to loop through all the fields:

public String getNameField( SObjectType sobjectType ) {

    DescribeSObjectResult objDescribe = sobjectType.getDescribe();

    Map<String, SObjectField> fieldsMap = objDescribe.fields.getMap();

    for ( SObjectField fieldToken : fieldsMap.values() ) {

        DescribeFieldResult fieldDescribe = fieldToken.getDescribe();

        if ( fieldDescribe.isNameField() ) {
            return fieldDescribe.getName();
        }

    }

    return 'Name'; // default
}
  • 2
    You could do the describe for the Name field first and only check all fields if that isn't it. More efficient (on average) but not very elegant... – Keith C Nov 22 '16 at 21:39
9

Elegant? Perhaps not, but checking 'Name' first and only iterating as a fallback plan should be more efficient. With every custom object and most standard objects, this shortcut will cut out the looping and additional describes entirely.

My natural inclination is to start with a positive condition:

public static String getNameField(SObjectType sObjectType)
{
    Map<String, SObjectField> fields = sObjectType.getDescribe().fields.getMap();
    if (fields.containsKey('Name') && fields.get('Name').getDescribe().isNameField())
    {
        return 'Name';
    }

    // iteration logic

    return 'Name'; // fallback if iteration fails
}

It may be more elegant, however, to use a negative condition and DRY on the return 'Name' front.

public static String getNameField(SObjectType sObjectType)
{
    Map<String, SObjectField> fields = sObjectType.getDescribe().fields.getMap();
    if (!fields.containsKey('Name') || !fields.get('Name').getDescribe().isNameField())
    {
        // iteration logic
    }
    return 'Name';
}
| improve this answer | |
  • In the event Name field was not actually, well, the naming field, should the if condition be if ( fields.containsKey( 'Name' ) && fields.get( 'Name' ).getDescribe().isNameField() ) { return 'Name' } else { ... iteration logic ... } ? – Doug Ayers Nov 22 '16 at 21:50
  • I'm getting foggy on my boolean logic here with negative || vs. positive &&. Might be the same thing, but the way you have it guarantees a final return statement at the end for compilation. – Doug Ayers Nov 22 '16 at 21:53
  • 1
    But then you also return 'Name' if the iteration fails to find one. Hence using this condition, you only have to return 'Name' once in your code. Since you asked for a more elegant solution, I considered this inversion of the condition more so. – Adrian Larson Nov 22 '16 at 21:53
  • Good point, and the odds that a standard Name field isn't a naming field is probably nil. Thanks! – Doug Ayers Nov 22 '16 at 21:54
  • 1
    Another reason not to loop through looking for isNameField is that when you have Person Accounts enabled, the Account object fields FirstName, LastName and Name all have isNameField true. Chances are you want Name! – James Jan 6 at 16:34
2

A little late to the party, but SOQL could help here too:

SELECT QualifiedApiName
FROM FieldDefinition
WHERE EntityDefinition.QualifiedApiName IN :listOfSObjectNames
AND IsNameField = TRUE

It does consume one query but that is probably more efficient than looping through describes.

| improve this answer | |
  • Not too late for me! This is perfect for the situation I just found myself in :) – Matt Lacey Jul 23 at 4:18

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.