function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
essess 

Mixed_DML_operation

To auto populate the standard employee number field on user object I have created auto no field and using a trigger on object user on after insert I am updating also . Also as per my requirement I have to also create a contact record on the after insert of user . But is not allowing me to do both the dml operation together.

 

the code is as follows:

trigger employeenoautopopulate on User (after insert)
{
 
     List<Contact> Con = new List<Contact>();
 
     for(User usr: Trigger.new)
     {
             System.debug('****** condition true');
             Contact con_temp = new Contact();
             con_temp.FirstName = usr.FirstName;
             con_temp.LastName = usr.LastName;
             con_temp.Date_Of_Joining__c = usr.Date_of_Joining__c;
             con_temp.User__c = usr.Id;
             con_temp.OwnerId = usr.Id;
             con_temp.Employee_Number__c = usr.Employee_Number__c;
             Con.add(con_temp);
      }  
      if(Con.size()>0)
      {
       insert Con;
        System.debug('****** insert done');
      }
   
     Set<Id> userid = new Set<Id>();
     for(User usr: Trigger.new)
     {
  
         userid.add(usr.Id);   
     }
  
     User[] usr = [select Id, EmployeeNumber,Employee_Number__c from user where Id in :userid];
     for(Integer i=0;i<usr.size();i++)
     {
        usr[i].EmployeeNumber = usr[i].Employee_Number__c ;
        System.debug('****'+usr[i].Employee_Number__c);
     }
      
      update usr;
      System.debug('****** update done');
}

 

I am getting following exception:

 

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger employeenoautopopulate caused an unexpected exception, contact your administrator: employeenoautopopulate: execution of AfterInsert caused by: 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): Contact, original object: User: []: Trigger.employeenoautopopulate: line 20, column 8
 

 

RajanJasujaRajanJasuja

Hi,

There are two types of objects in SFDC. "Setup" objects and "None setup" objects.

 

 Setup objects are 

* User

* RecordType

* Profile

 etc

and all other general objects i.e.

* Contact

* Account

* Lead

etc

are the None setup objects.

If you run a DML operation on setup object you can't run a DML operation on None setup object in the same context, it will show the "Mixed_DML_operation" error.

Salesforce don’t allow you to run DML operations on both Setup and None Setup objects in the same context.

essess
can anyone suggest an alternative solution to this
hisrinuhisrinu
Try with @future
MakMak
Yes, it will work with @future.
essess

Ya it is working with @future. But when I run the test method for it , test is a failure with the same error . The following are the codes:

 

testmethod:

 

public class test_user
{
  static testmethod void test()
  {
        User user = new User();
        user.FirstName ='Tango';
        user.LastName = 'Charlie';
        user.Date_of_Joining__c= date.newInstance(2009, 6, 18);
        user.Email = 't.charlie@email.com';
        user.Username ='tango.c@ess.com';
        user.Alias ='tango.c';
        user.TimeZoneSidKey = 'America/New_York';
        user.LocaleSidKey = 'en_US';
        user.EmailEncodingKey = 'ISO-8859-1';
        user.ProfileId = [select id from Profile where Name='System Administrator'].Id;
        user.LanguageLocaleKey = 'en_US';
        user.UserRoleId =[select id from UserRole where Name= 'Team Member'].Id;
        insert user;
      
       
  }
}

 

trigger:

 

 

trigger employeenoautopopulate on User (after insert) 
{


Set<Id> userid = new Set<Id>();
for(User usr: Trigger.new)
{

userid.add(usr.Id);
}

emp_update.user_update(userid);
emp_update.contact_insert(userid);


}

 

 

class emp_update:

 

public class emp_update {

public static void user_update(Set<Id> userid)
{
User[] usr = [select Id, EmployeeNumber,Employee_Number__c from user where Id in :userid];
for(Integer i=0;i<usr.size();i++)
{
usr[i].EmployeeNumber = usr[i].Employee_Number__c ;
System.debug('****'+usr[i].Employee_Number__c);
}

update usr;
System.debug('****** update done');

}

@future
public static void contact_insert(Set<Id> userid)
{
List<Contact> Con = new List<Contact>();

User[] usr = [select Id, EmployeeNumber,Employee_Number__c,FirstName,LastName,Date_of_Joining__c from user where Id in :userid];
for(Integer i=0;i<usr.size();i++)
{
System.debug('****** condition true');
Contact con_temp = new Contact();
con_temp.FirstName = usr[i].FirstName;
con_temp.LastName = usr[i].LastName;
con_temp.Date_Of_Joining__c = usr[i].Date_of_Joining__c;
con_temp.User__c = usr[i].Id;
con_temp.OwnerId = usr[i].Id;
con_temp.Employee_Number__c = usr[i].Employee_Number__c;
Con.add(con_temp);
}

if(Con.size()>0)
{
insert Con;
System.debug('****** insert done');
}

}
}

 

osamanosaman

There is a work around for that.

If you want to perform two DML operations sequentially, create a seprate method for 2nd DML operation with @future token.

make sure you put System.RunAs() in the method. Your overall method should look like this

 

private static void myFunc()

{

     ///1st DML operation

 

     User usr = [Select id from User where Id = :UserInfo.getUserId()];

 

     System.RunAs(usr)

     {

        Test.startTest();

         myFunc2();

         Test.stopTest();

     }

 

 

}

 

@future

private static void myFunc2()

{

   ///2nd DML operation

}

FinnArildFinnArild

But what if you already are in a @future call? ... Yeah - I know: "Don't Be"

 

Well - I'll have to figure a way around it.

Chandan3955Chandan3955

Thanks for the info..!!