Custom settings allow users to have greater control over parameters referenced in Apex classes. Since the Summer ’15 release, Salesforce has offered the option of using custom metadata types as an alternative to custom settings. Custom metadata types have many advantages over custom settings, but there are some cases where custom settings should still be used.
Building a custom metadata type is very similar to building a custom object. The main difference that you will notice is the suffix of __mdt at the end of the custom metadata type as opposed to the usual __c. They can be built under Setup | Custom Metadata Types.
Choosing Custom Metadata Types
The most obvious advantage of custom metadata types is that they simplify the deployment process. After deploying custom settings, the data stored in those settings will not be transferred to the destination. The data must then be loaded either manually, using a data migration tool, or by using an Apex script. All of these options require either more time or more development. With custom metadata types, since everything is metadata, those settings are immediately available after deployment. This is especially useful when developing a package, where the deployment could be to multiple organizations.
Though in beta as of Summer ’16, custom metadata types have the ability to build a metadata relationship field, where two custom metadata types can be related through a parent child relationship. This feature does not exist for custom settings. Read about the Spring ’16 release.
Another benefit of custom metadata types over custom settings is the ability to query for custom metadata types from within a test class. Custom metadata types are visible to all test classes without setting the @seeAllData annotation to true. This is a huge advantage over custom settings because custom settings need to be recreated in your test classes. Using custom metadata types can also avoid the collisions that occur when trying to run test classes asynchronously. Test classes that would normally pass when run synchronously will often fail when run asynchronously due to the test classes attempting to insert similar custom setting data at the same time.
Below is a quick example of how custom metadata types could potentially be used. Suppose we wish to store the Federal Minimum Wage within Salesforce. We might wish to build a Visualforce page in order to quickly reference this data within Salesforce:
The Controller:
public class MinimumWageController {
public List<Minimum_Wage__mdt> wages {get;set;}
public MinimumWageController() {
Map<ID,Minimum_Wage__mdt> allWages = new Map<ID,Minimum_Wage__mdt>([SELECT ID, Year__c, Wage__c FROM Minimum_Wage__mdt]);
wages = allWages.values();
}
}
The Visualforce page:
<apex:page controller="MinimumWageController" >
<apex:pageBlock title="Minimum Wage by Year">
<apex:pageBlockTable value="{!wages}" var="w">
<apex:column value="{!w.Year__c}"/>
<apex:column value="{!w.Wage__c}"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:page>
The Visualforce Page will look like:
If you don’t expect your data to change during the lifetime of a transaction, custom metadata types might be a better solution than custom settings.
Choosing Custom Settings
Hierarchy custom settings have the ability to choose different values based on the user that has invoked an operation. If the settings need to change based on a user or profile, you should still use custom settings. Another disadvantage of using custom metadata types is that they cannot be updated using DML operations. While it’s possible to update these values through the Metadata API, there is a lot of overhead in performing this type of operation. A much easier solution would be to use list custom settings, which can be updated through DML operations.
Suppose an organization wishes to perform quality checks on the data being entered into Salesforce but wants to do this randomly in order to limit the number of records that require review. A developer might be tasked with marking a checkbox on an Account for every tenth account that is entered into Salesforce. Once the counter reaches ten, the counter reverts back to zero and marks a checkbox on the current account. This is one case where using list custom settings would be a better solution, because the setting needs to be updated each time an account is inserted.
Trigger:
trigger AccountTrigger on Account (before insert) {
if(trigger.isBefore && trigger.isInsert){
new AccountTriggerHandler().beforeInsert(trigger.new);
}
}
Trigger Handler:
public class AccountTriggerHandler {
public void beforeInsert(List<Account> accountList){
//grab the custom setting
Account_Counter__c acctCounter = Account_Counter__c.getInstance('Account Counter');
for(Account a : accountList){
acctCounter.Counter__c++;
if(acctCounter.Counter__c == acctCounter.Counter_Limit__c){
a.Selected_By_Counter__c = true;
acctCounter.Counter__c = 0;
}
}
update acctCounter;
}
}
Custom metadata types are generally an improvement over custom settings, but care must be used in deciding which one to implement. If the settings only change through a user edit or data upload, then custom metadata types are most likely the correct choice. On the other hand, if the settings change frequently due to the result of a transaction, it might be better to stick with custom settings.
Questions?
Have questions? Let us know in a comment below, or contact our team directly. You can also check out our other posts on customizing your Salesforce solution.
Pingback: Making the Move to Custom Metadata Types ΓÇô FileMaker Source
A good article. I would add a caution about one thing, though:
“On the other hand, if the settings change frequently due to the result of a transaction, it might be better to stick with custom settings.”
If settings need to change in code *occasionally*, even regularly (as in a few times a day), I agree with this. But if settings are actually changing really frequently, I’d caution against even using custom settings. Custom settings (and custom metadata types) are cached, which means they’re optimized for cases where the read/write ratio is high. Making a change invalidates the cache, which means that making constant changes is going to impact your performance.
If you really need stuff that’s going to change minute-to-minute (let alone millisecond-to-millisecond), regular custom objects are the way to go.
Thanks Taylor. Was reading up on MDTs and look who it is! Hope all is well.