Mixed DML Operation Error (MIXED_DML_OPERATION) in Salesforce Apex Classes, Apex Triggers, Test Classes and Flows Explained.

1. What is Mixed DML Operation Error?

You will get Mixed DML Operation Error (MIXED_DML_OPERATION) when you try to perform DML on setup objects(User, User Role), along with DML on other sObjects (non-setup Object such as Account, Contact) (or vice versa) in the same transaction.

2. Steps to Reproduce Mixed DML Operation Error

  1. Create a Flow or Apex Trigger on User Object
  2. In the Flow or Apex Trigger try to activate the user
  3. In the same Flow or Apex Trigger try inserting an account
  4. Try updating a User record so that Flow or the Apex Trigger is fired

3. How to Resolve Mixed DML Operation Error?

3.1 Apex

3.1.1 Trigger/Classes

  1. Create a method that performs a DML operation on one type of sObject
  2. Create a second method that uses the @future annotation to manipulate a second sObject type
public class MixedDMLError {
    public static void insertUserandLead() {
        Profile pro = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='Blogger'];
        User usr = new User(alias = 'dy', email='dineshyadav@forcepective.com', 
            emailencodingkey='UTF-8', lastname='Yadav', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = pro.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='dinesh.yadav@forcepective.com');
        insert usr;
        Handler.insertLead(new Lead(lastname = 'Yadav')); 
    }
}
public class Handler {
    @future
    public static void insertLead(Lead testLead) {
        insert testLead;
    }
}

3.1.2 Test Classes

Test methods allow for performing mixed Data Manipulation Language (DML) operations that include both setup sObjects and other sObjects if the code that performs the DML operations is enclosed within System.runAs method blocks. You can also perform DML in an asynchronous job that your test method calls.

@isTest
private class MixedDMLErrorTestClass {
    static testMethod void mixedDMLErrorTestMethod() {  
        User usr;
        Lead testLead;
        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
        System.runAs (thisUser) {
            Profile profStandard = [SELECT Id FROM Profile WHERE Name='Standard User'];
            UserRole roleBlogger = [SELECT Id FROM UserRole WHERE Name='Blogger'];
            usr = new User(alias = 'dyadav01', email='dineshyadav@forcepective.com', 
                emailencodingkey='UTF-8', lastname='Yadav', 
                languagelocalekey='en_US', 
                localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
                timezonesidkey='America/Los_Angeles', 
                username='dineshyadav@forcepective.com');
            insert usr;
            testLead = new Lead(lastname ='Dinesh');
            insert testLead;
        }
    }
}

3.2 Flows

3.2.1 Screen Flow

Add a Screen Element or Local Action between Updating User and Creating Lead Actions

3.2.2 Autolaunched Flow

Add a Pause Element between Updating User and Creating Lead Actions

3.2.3 Record-Triggered and Platform Event-Triggered Flows

Since Pause Element is not available in Record-Triggered and Platform Event-Triggered Flows. Using Pause Element is not an option. A possible solution could be to separate the User Activation and Lead Creation process into two different flows. Create an Apex Invocable Action to call the second flow asynchronously. Use the Invocable Apex Action in User Activation flow to invoke Lead Creation Flow.

Additional Resources

Recommended Articles:

Please Leave a Comment