About Me

My photo
PLANO, Texas, United States

Tuesday, May 28, 2013

MIXED_DML_OPERATION

“MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object: Contact

You can easily run into this error if you are trying to perform DML on setup and non-setup objects in the same transaction. Non-Setup objects can be any one of standard objects like Account or any custom object, whereas a “setup" object is one that must be edited from the setup or builder area of the platform. These objects include the User object, Organization object, Email templates and so on. Here are few examples of the Setup Objects
1.     Group1
2.     GroupMember
3.     QueueSObject
4.     User2
5.     UserRole
6.     UserTerritory
7.     Territory

Error Conditions :
You can get this error in two blow conditions
1.     Non-Test code (Non-Test code means any Apex code that is not written for test cases)
2.     Test Code
      For Non-Test Class  
      Use Future method to resolve this issue.
      I got this error few month back when I was writing the Trigger on Contact whenever someone make Contact Inactive then its associated Owner become inactive.  
 trigger UpdateContactTrigger on Contact (after update)
 {
       List<User> lstUser = new List<User>();
       for(Contact oContact : Trigger.New){
          if(oContact.isActive__c == false && oContact.isActive__ c! =     Trigger.oldMap.get(oContact.Id).isActive__c){
             User oUser = new User(Id=oContact.OwnerId);
             oUser.IsActive = false;
             lstUser.add(oUser);}
            }
                   if(lstUser != null){
                    update lstUser;
               }
         }
       Below are the workaround for this Trigger:
 Trigger :
trigger MakeUserInactiveTrigger on Contact (after update) 
{
    List<Id> sUser = new List<Id>();
   for(Contact oContact : Trigger.New){
       if(oContact.isActive__c == false && oContact.isActive__c !=Trigger.oldMap.get(oContact.Id).isActive__c) {
           sUser.(oContact.OwnerId);
       }
    }
    UpdateUserUtil.updateUser(sUser);
}

Future Class to handle this Exception:

global class UpdateUserUtil
{
    @future    
    public static void updateUser(List<> userId) 
    {     
        List<User> lstUser = new List<User>();
        for( User oUser : [select IsActive,Id   from User  where Id=:userId]) 
        {
                  User u = new User(Id=oUser.Id);
                  u.isActive = false; 
                  lstUser.add(u);
        }
        if (lstUser != null) 
        {    
            upadate lstUser;
        }
}

In this way, we can resolve the issue. So use future method to resolve this error.

     For Test Class  
     Use system.runAs() Method to resolve this issue.
      In Above method, We are using the currently updated User ID in Creation in the Sony Account  Team(Custom Object)
     Public static testMethod void EmailAddressLookup() {
            Test.startTest();
            User uID=SFE_UtilForSFE.CreateUser('newUser','newuserTY@testorg.com','Testing','newuser@testorg.com');
            uID.IsActive = true;
            update uID;
            Account oAccount = SFE_UtilForSFE.CreateAccount('Test Account','678906',null,'AE11');
            Contact oContact = SFE_UtilForSFE.createContact('testContact',oAccount.ID );
            oContact.Email = 'newcontact@testorg.com';
            update oContact;
            Sony_Account_Team__c oSAT=SFE_UtilForSFE.Create_Sony_Account_Team('Testsat',oAccount.id,uID.ID );
           Test.stopTest();
    }
  
So Once I run the test class I got MIXED_DML_OPERATION, DML error and to resolve this error, I used System.RunAs() like below :

public static testMethod void EmailAddressLookup()
{
       Test.startTest();
       User uID=SFE_UtilForSFE.CreateUser('newUser','newuserTY@testorg.com','Testing','newuser@testorg.com');
       uID.IsActive = true;
       update uID;
       List<User> lstUsers = [select Id, ContactId, AccountId from User where Id =:uID.Id];
       if(lstUsers != null && lstUsers.size() > 0)
       {
            User userInstance = lstUsers[0];
            system.runAs(userInstance)
            { 
                Account oAccount = SFE_UtilForSFE.CreateAccount('Test Account','678906',null,'AE11');
                Contact oContact = SFE_UtilForSFE.createContact('testContact',oAccount.ID );
                oContact.Email = 'newcontact@testorg.com';
                 update oContact;
                Sony_Account_Team__c oSAT=SFE_UtilForSFE.Create_Sony_Account_Team('Testsat',oAccount.id,uID.ID );
            }
       }
      Test.stopTest();
}   

So this is what I came out from this error.

Hope this will help in understanding or learning purpose. 

Thanks










No comments:

Post a Comment