I'm creating some prep apex to run when we receive an account .csv that we've automated daily to push into salesforce. The idea is that some of these fields we want them to update our primary fields on insert, but otherwise just host them somewhere else for a later audit.

One of these items is an external Id (Customer_Id__c) which is intended to update the account.parent field. I've been reading around for the better part of the afternoon and have followed the code on Relating Records by Using an External ID.

For some reason, it's not working and I'm not sure if it's because it's firing on a before trigger, or if there's something I'm overlooking.

if(account.Nav_Parent_Id__c != null) 
    account.Parent = new Account(Customer_ID__c = account.Nav_Parent_Id__c);    

To clarify how it's not working, there are no exceptions and the account.parent is not being set. I formerly had the code split out like this:

if(account.Nav_Parent_Id__c != null) {
    Account parentAccount = new Account(Customer_ID__c = account.Nav_Parent_Id__c);
    account.Parent = parentAccount;
    system.debug('parent account' + account.Parent);
    system.debug('parent account' + account.ParentId);

The debug logs returned this:

16:58:29:821 USER_DEBUG [23]|DEBUG|parent accountAccount:{Customer_ID__c=TESTTEST}
16:58:29:821 USER_DEBUG [24]|DEBUG|parent accountnull

Yes, Customer_ID__c is set as an external Id on the account and yes, there is a test record in this sandbox that has a customer_Id__c of TESTTEST. Its expected accountId is 0013000000LebhhAAB.

Any thoughts?

  • 1
    How is it not working? Are you seeing an exception or? – Brian Mansfield Jun 21 '16 at 21:39
  • I'll update the question rq. – kkorynta Jun 21 '16 at 21:40
  • 1
    ParentId won't be populated until you re-query for it. Is it not populated after the DML Operation commits to the database? – Adrian Larson Jun 21 '16 at 21:50
  • That sounds right. 1st time attempting to utilize an external url in apex, wasn't sure what to expect. – kkorynta Jun 22 '16 at 17:09

The external ID field has to be set before the transaction starts (those records are resolved ahead of time). I'd probably suggest a recursive update on insert:

// Run this after insert
Account[] clones = Trigger.new.deepClone(true, false, false);
for(Account record: clones) {
    if(record.Nav_Parent_Id__c != null) {
        record.Parent = new Account(Customer_Id__c = record.Nav_Parent_Id__c);
update clones;

You are allowed to have a record in both an insert and update trigger at the same time, so this should work just fine.

| improve this answer | |
  • You mentioned this needs to be run in an after insert/update dml? Does that mean that this will not work in a before insert dml? – kkorynta Jun 22 '16 at 14:04
  • @kkorynta Correct. It's "too late" to specify an external ID at that point in the execution, as I understand it. There's simply no way to make it work, as external ID values are loaded before the before insert trigger has a chance to run. Of course, at that point, if you wanted to stay with a before insert trigger, you could just query the records directly. – sfdcfox Jun 22 '16 at 14:53
  • Understood. I'm not going to go the query route as these .csv files for accounts is roughly 21k records and it will grow over time. I thought it would be best to utilize the external Id instead of adding another query that's pulled to the method. For now I'll just split it the parent account update into a separate method and call it in the after insert trigger. Thanks for confirming. – kkorynta Jun 22 '16 at 17:04
  • Spoke too soon. Has to be a before trigger - otherwise you get this: Insert Row Failed: AccountTrigger: execution of AfterInsert caused by: System.Exception: Record is read-only Class.AccountNavicureFeed.prepForInsertParentAccount: line 49, column 1 Trigger.AccountTrigger: line 57, column 1 – kkorynta Jun 22 '16 at 17:21
  • @kkorynta You need to clone the original records, as demonstrated in my trigger example. You can't update the exact objects in Trigger.new, but you can update those records by Id when you clone them. Also, a query in the trigger isn't the same as needing a query to update your csv. In fact, that's kind of the point of using a before insert trigger. – sfdcfox Jun 22 '16 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.