31

I need to be able to check if an org has Person Accounts enabled via Apex Code as part of package. What's the best way to do this without making the package require Person Accounts be enabled in any org in which it's installed?

1 Answer 1

40

Method 1

Try to access the isPersonAccount property on an Account and catch any exception that occurs if that property is missing. If an exception is generated then person accounts are disabled. Otherwise they're enabled. To avoid making person accounts required for the package you assign the Account object to an sObject and use sObject.get( 'isPersonAccount' ) rather than accessing that property directly on the Account object.

This method takes ~3.5ms and negligible heap space in my testing.

// Test to see if person accounts are enabled.
public Boolean personAccountsEnabled()
{
    try
    {
        // Try to use the isPersonAccount field.
        sObject testObject = new Account();
        testObject.get( 'isPersonAccount' );
        // If we got here without an exception, return true.
        return true;
    }
    catch( Exception ex )
    {
        // An exception was generated trying to access the isPersonAccount field
        // so person accounts aren't enabled; return false.
        return false;
    }
}

Method 2

Use the account meta-data to check to see if the isPersonAccount field exists. I think this is a more elegant method but it executes a describe call which counts towards your governor limits. It's also slightly slower and uses a lot more heap space.

This method takes ~7ms and ~100KB of heap space in my testing.

// Check to see if person accounts are enabled.
public Boolean personAccountsEnabled()
{
    // Describe the Account object to get a map of all fields
    // then check to see if the map contains the field 'isPersonAccount'
    return Schema.sObjectType.Account.fields.getMap().containsKey( 'isPersonAccount' );
}
5
  • 2
    I prefer Method 2. The heap space shouldn't be a concern - it's freed after the function exits. In practice you'll want to cache the result in a static variable so you don't make a describe call every time you check in a context. So it's only one Describe call per execution context. Plus, in a larger app you can use a single Describe to check for other fields that may or may not be present (such as DunsNumber, RecordType) so you may be making the call anyway. Besides, as you say - #2 is more elegant :-)
    – kibitzer
    Commented Aug 31, 2012 at 20:00
  • 2
    Yeah, I was going to mention caching the variable at the end of the response for exactly that reason but forgot to tack that on. For me, 100KB of heap can be problematic at times depending on when it happens and 3.5ms extra execution time is also an issue for me since in my application a lot of work has to be done in triggers so every little bit of optimization helps. I listed them both since #1 fits my needs more closely but #2 is more elegant and probably a more correct way of solving the problem. Commented Aug 31, 2012 at 20:09
  • Great answer! I tend to agree with #2 since there are other possible ways that an exception can get thrown (or could be introduced into the code later) which would produce a false positive, where the describe approach is very specific. But of course, there's always the limits to consider, and perhaps by being more specific in the exception handling you could distinguish between any general error and an SObjectException error (ie: System.SObjectException: Invalid field isPersonAccount for Account).
    – Adam
    Commented Sep 1, 2012 at 18:23
  • Updated with a better method that was added in API 38.0. Commented Feb 15, 2018 at 4:40
  • 1
    With the API V49.0 the New method does not work, could you update your answer thanks @E.J.Wilburn
    – benahm
    Commented Jul 13, 2020 at 14:34

You must log in to answer this question.

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