You need to sign in to do that
Don't have an account?

Mixed DML error on Trigger that is only inserting and updating Contact object
I have found some info out there about Mixed_DML errors, but most of them have to do with Controllers and action chaining for VF pages.
I am getting one on a trigger that attempts to do the following:
Up until this point every employee gets a seat in our SFDC org. We also make a Contact record for every employee to record cases, training etc. Therefore, I wanted to make a trigger that created a Contact whenever a new User record is created or upates the Contact whenever the corresponding User is edited. So the following is what I started with. The logic isn't complete, but there is enough there to get started. Anyway. it's giving me the following when I try to test by creating a new user in the interface.
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: []
What I'm confused by(take warning here, I'm a completely self-taught novice and struggling) is that the docs say that mixed dml errors occur because a single method is trying to manipulate two different sObjects, and that the solution is to have the two dml statements in two different methods one of which is tagged with @future. However, I am only trying to run DML on the Contact object, so what's the deal?
BTW, I'm totally open to people making suggestions on how to make this code more efficient, elegant etc.
Thanks!
trigger userTrigger on User (after insert, after update) { List<Contact> newCons = new List<Contact>(); List<Contact> exCons = new List<Contact>(); if(trigger.isInsert) { for(User newU : trigger.new) { Contact theCon = new Contact(); theCon.FirstName = newU.FirstName; theCon.LastName = newU.LastName; theCon.Email = newU.Email; theCon.Department =newU.Department__c; theCon.Unit__c = newU.Unit__c; theCon.StartDate__c = newU.DateofHire__c; theCon.EndDate__c = newU.TerminationDate__c; theCon.Title = newU.Title; theCon.Phone = newU.Phone; theCon.AccountId = '001Q000000G7LHh'; newCons.Add(theCon); } } insert newCons; if(trigger.isUpdate) { List<Contact> existingCons = [select ID, FirstName, LastName, Email, Department, Unit__c, StartDate__c, EndDate__c, Title, Phone from Contact where Id IN :trigger.newMap.keySet()]; for(Contact existingCon : existingCons) { if(existingCon.FirstName != trigger.newMap.get(existingCon.Id).FirstName) { existingCon.FirstName = trigger.newMap.get(existingCon.Id).FirstName; } if(existingCon.LastName != trigger.newMap.get(existingCon.Id).LastName) { existingCon.LastName = trigger.newMap.get(existingCon.Id).LastName; } if(existingCon.Email != trigger.newMap.get(existingCon.Id).Email) { existingCon.Email = trigger.newMap.get(existingCon.Id).Email; } if(existingCon.Department != trigger.newMap.get(existingCon.Id).Department__c) { existingCon.Department = trigger.newMap.get(existingCon.Id).Department__c; } if(existingCon.Unit__c != trigger.newMap.get(existingCon.Id).Unit__c) { existingCon.Unit__c = trigger.newMap.get(existingCon.Id).Unit__c; } if(existingCon.StartDate__c != trigger.newMap.get(existingCon.Id).DateofHire__c) { existingCon.StartDate__c = trigger.newMap.get(existingCon.Id).DateofHire__c; } if(existingCon.EndDate__c != trigger.newMap.get(existingCon.Id).TerminationDate__c) { existingCon.EndDate__c = trigger.newMap.get(existingCon.Id).TerminationDate__c; } if(existingCon.Title != trigger.newMap.get(existingCon.Id).Title) { existingCon.Title = trigger.newMap.get(existingCon.Id).Title; } if(existingCon.phone != trigger.newMap.get(existingCon.Id).phone) { existingCon.phone = trigger.newMap.get(existingCon.Id).phone; } //newCons.add(existingCon); } } update exCons; }
While you aren't making any changes to a setup object, the transaction that you are in has already inserted/updated a user record so I think you are hitting problems due to that.
Thanks Bob.
I have broken up the insert and update statements into two methods and have tagged both with @future. This got the insert working well, but opened up other problems with the update. I am going to struggle with it on my own for a bit, but may post again if I give up.
I'm doing something similar but I only get the MIXED DML exception on After Insert. After Update seems to work fine.
Hey,
I did this a while ago, so not sure what the solution was but this code is working for me.
Yup, that should work fine since it's being executed in a future context.
I'm working on a functionality to sync a User with a Contact , all of this process is handled with triggers and it seems that the save behavior for a User is different when created through the web interface since I only get MIXED_DML exceptions when creating users through the UI.
What I ended up doing is that I look for a MIXED_DML exception in my trigger , if this happens I do a second attempt to insert/update contacts but in a future method. I did it this way because I wan't to use future calls the least I can, I don't have a lot of full salesforce/force.com licenses in my ORG and I don't want to hit a governor limit for daily future calls.
...
Sorry but I can't resist to warn you of those hardcoded IDs in your code, always got to watch out on those otherwise you're going to have a lot of fun when deploying this.
Point taken on your advice about hard coding. I just didn't feel like writing soql statements to pull two record types, and two accounts. The code is live, with fingers crossed.
anyway, I just wanted to clarify that these methods are being called by a trigger...so my project is similar to yours in that we're both trying to sync users and contacts. I also experienced some weird behavior with mixed dml statements. In my case the error would throw when I ran tests in SFDC testing envirnonment, but the errors were not thrown when I ran the tests in eclipse. This was confusing so I tried validating a deployment in Eclipse and no errors were thrown.
Were you getting the MIXED_DML exceptions only when running tests through the web interface or you just had different test coverage %?
There's a weird bug with test coverage % when running tests through the web.
No I had 0% coverage with mixed dml messages in the interface. My coverage was fine in eclipse. And, this sounds really stupid now, but I deployed via Eclipse and now that the code is in production it is throwing the same error when I run test through production user interface.