SOQL Custom Metadata in Apex Class: Example and Best Practices

Custom Metadata in Salesforce is a powerful feature that allows you to define application configuration and use it within your Apex classes. By querying custom metadata with SOQL, you can retrieve dynamic configurations that are easily deployable and maintainable. This guide provides a clear example of how to use SOQL to query custom metadata in an Apex class, along with best practices for implementation.


What Is Custom Metadata in Salesforce?

Custom Metadata Types are similar to custom objects, but they are specifically designed to store metadata rather than transactional data. Key features include:

  • Deployability: Custom metadata records can be deployed across environments using change sets or metadata API.
  • SOQL Queryable: You can query custom metadata records using SOQL in Apex.

Common use cases include:

  • Application configuration.
  • Business logic rules.
  • Threshold or limit values.

Defining a Custom Metadata Type

  1. Navigate to Setup > Custom Metadata Types.
  2. Click New Custom Metadata Type and define fields.
  3. Add records to the custom metadata type with relevant values.

Example:

Custom Metadata Type Name: Discount_Settings__mdt
Fields:

  • Field Name: Discount_Percentage__c (Number)
  • Field Name: Region__c (Text)

Querying Custom Metadata with SOQL in Apex

1. Example Custom Metadata Records

Region Discount Percentage
US 10%
EU 15%

2. Apex Class to Query Custom Metadata

public class DiscountService {
    public static Decimal getDiscount(String region) {
        // Query the custom metadata using SOQL
        Discount_Settings__mdt discountSetting = [
            SELECT Discount_Percentage__c 
            FROM Discount_Settings__mdt 
            WHERE Region__c = :region
            LIMIT 1
        ];
        
        // Return the discount percentage
        return discountSetting.Discount_Percentage__c;
    }
}

Key Points:

  • Use SELECT to query specific fields from the custom metadata type.
  • Use a WHERE clause to filter records based on criteria.
  • Use LIMIT 1 if you expect only one matching record.

3. Using the Apex Class

public class ShoppingCart {
    public static void applyDiscount(String region, Decimal totalAmount) {
        Decimal discount = DiscountService.getDiscount(region);
        Decimal discountedAmount = totalAmount - (totalAmount * (discount / 100));
        
        System.debug('Discounted Amount: ' + discountedAmount);
    }
}

Example Usage:

ShoppingCart.applyDiscount('US', 1000);
// Output: Discounted Amount: 900

Handling Multiple Custom Metadata Records

If you need to retrieve multiple records, use a List to store results.

public class DiscountService {
    public static Map<String, Decimal> getAllDiscounts() {
        Map<String, Decimal> discountMap = new Map<String, Decimal>();

        // Query all custom metadata records
        List<Discount_Settings__mdt> discountSettings = [
            SELECT Region__c, Discount_Percentage__c 
            FROM Discount_Settings__mdt
        ];
        
        // Populate the map
        for (Discount_Settings__mdt setting : discountSettings) {
            discountMap.put(setting.Region__c, setting.Discount_Percentage__c);
        }
        
        return discountMap;
    }
}

Best Practices for Using Custom Metadata in Apex

1. Query Optimization

  • Use LIMIT and filters to minimize unnecessary data retrieval.
  • Avoid querying custom metadata repeatedly in a single transaction. Instead, cache results.

2. Use Maps for Efficient Lookups

  • Load custom metadata records into a Map for quick access.

Example:

Map<String, Decimal> discountMap = DiscountService.getAllDiscounts();
Decimal discount = discountMap.get('US');

3. Avoid Hardcoding

  • Store configurable values, such as thresholds, in custom metadata instead of hardcoding them in Apex.

4. Deploy and Manage with Change Sets

  • Ensure custom metadata records are included in your deployments to maintain consistency across environments.

5. Error Handling

  • Handle scenarios where no records are found or fields are null:
if (discountSetting == null || discountSetting.Discount_Percentage__c == null) {
    throw new CustomException('Discount setting not found for the given region.');
}

Common Use Cases

  1. Region-Specific Discounts:
    • Configure discounts for different regions or customer types.
  2. Threshold Values:
    • Define configurable limits for validations or processes.
  3. Dynamic Business Logic:
    • Use metadata for feature toggles or decision-making rules.

Conclusion

Using SOQL to query custom metadata in Apex provides a flexible and scalable way to manage application configurations. With the examples and best practices outlined in this guide, you can efficiently implement custom metadata queries in your Salesforce applications, ensuring maintainability and adaptability for future changes.