Mixed DML Operation Error in Salesforce

I hope you got the got Mixed DML Operation Error in Salesforce while working with a Test class, or doing some automation on a user object. Let’s see how to fix the Mixed DML Operation Error in Salesforce and avoid the MIXED-DML-OPERATION error.

What is a Mixed DML Operation Error?

A mixed DML Operation Error comes when you try to perform DML operations on setup and non-setup objects in a single transaction. DML operations on certain sObjects, sometimes referred to as setup objects, can’t be mixed with DML on other sObjects in the same transaction.

Mixed DML Operation Error in Salesforce

This restriction exists because some sObjects affect the user’s record access in the org. You must insert or update these types of sObjects in a different transaction to prevent operations from happening with incorrect access-level permissions. 

For example, you can’t update an account and a user role in a single transaction.

What is Setup Object?

Setup objects are the sObjects that affect the user’s access to records in the organization. Here are examples of the Setup Objects:

  1. ObjectPermissions
  2. PermissionSet
  3. PermissionSetAssignment
  4. QueueSObject
  5. Territory
  6. UserTerritory
  7. UserRole
  8. User

How to Fix MIXED DML Operation Error

We should perform DML operation on standard/custom object records in a different transaction. Let’s see how to avoid the MIXED DML Operation error:

  1. Use Future methods helps in avoiding mixed DML errors
  2. Mixed DML Operations in Test Methods
    • Mixed DML Operations in System.runAs Blocks
    • Use @future to Bypass the Mixed DML Error in a Test Method

Avoiding mixed DML errors using @Future method

We can use Future methods to avoid mixed DML errors in Salesforce. Let’s see when mixed Dml issues come in salesforce. In below code we are trying to insert the Account and user roles togather.

public class MixedDMLErrorDemo {

    public static void myMethod() {
        Account a = new Account(Name='ApexHours');
        insert a;
        
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='CEO'];
        User usr = new User(alias = 'apexs', email='[email protected]', 
            emailencodingkey='UTF-8', lastname='Hours', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='[email protected]');
        insert usr;
        
    }
}

When you will to execute the above code you will get “System.DmlException: Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa):” error.

Let’s see how to perform mixed DML operations by using a future method to perform a DML operation on the User object. We can simply move the Setup object transection into a future context to avoid it. Like the below code.

public class MixedDMLErrorDemo {
    public static void myMethod() {
        Account a = new Account(Name='ApexHours');
        insert a;
        UtilFutureDemo.insertUser();
    }
}

Use Future methods helps in avoiding mixed DML errors like below code.

public class UtilFutureDemo {
    @future
    public static void insertUser() {
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='CEO'];
        User usr = new User(alias = 'apexs', email='[email protected]', 
            emailencodingkey='UTF-8', lastname='Hours', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='[email protected]');
        insert usr;
    }
}

How do you resolve mixed DML exceptions in Test class?

We can use System.runAs Blocks in Salesforce to avoid Mixed DML Operations errors.

@isTest
private class MixedDMLTestClassDemo {
    
    static testMethod void mixedDMLExample() {  
        User u;
        
        Account a = new Account(Name='ApexHours');
        insert a;
        
        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];

        System.runAs (thisUser) {
            Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
            UserRole r = [SELECT Id FROM UserRole WHERE Name='CEO'];
           
            User usr = new User(alias = 'apexs', email='[email protected]', 
               emailencodingkey='UTF-8', lastname='Hours', 
               languagelocalekey='en_US', 
               localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
               timezonesidkey='America/Los_Angeles', 
               username='[email protected]');
            insert usr;
        }
        
    }
}

Use @future to Bypass the Mixed DML Error in a Test Method

You can also use the future method in the test class. Check out the example here.

Amit Chaudhary
Amit Chaudhary

Amit Chaudhary is Salesforce Application & System Architect and working on Salesforce Platform since 2010. He is Salesforce MVP since 2017 and have 17 Salesforce Certificates.

He is a active blogger and founder of Apex Hours.

Articles: 461

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *