Monday, December 23, 2013

MIXED_DML_OPERATION error in Salesforce.com

MIXED_DML_OPERATION,
 DML operations on certain sObjects can’t be mixed with other sObjects in the same transaction. This is because some sObjects affect the user’s access to records in the organization.
 These types of sObjects must be inserted or updated 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. However, there are no restrictions on delete DML operations.
 DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object: Account
 http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm

 Salesforce categorizes objects into so called setup and non-setup objects. User is a setup object while Contact is a non-setup object. Salesforce restricts DML operations so that both kinds of objects can't be manipulated in the same context.
 If you need to change User's IsActive field, add a custom IsActiveProxy field to the user and perform your update in a trigger on it: trigger
UpdateContactTrigger on Contact (after update)
{
 User u = [SELECT Id, IsActive FROM User WHERE IsActive = true];
 u.IsActiveProxy__c = false;
 update u;
 }
Then create a 'before update' trigger on a User that copies the proxy field value to the standard field:
 trigger BeforeUpdateUserTrigger on User (before update)
 {
 for(User user : trigger.new)
 {
 if(user.IsActive != user.IsActiveProxy__c)
 { user.IsActive = user.IsActiveProxy__c;
 }
 }
 }
 define @future method which will do the update and call this method from trigger.
 @future
 updateUser()
{
 User u = [SELECT Id, IsActive FROM User WHERE IsActive = true];
 u.IsActive = false;
 update u;
 }
 and call it in
trigger: trigger UpdateContactTrigger on Contact (after update)
{
 updateUser();
 }