“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;
}
{
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