Failure setting lookups in triggers when upserting multiple records of different types very quickly










2














I have an integration app that polls records of different types from an internal database every few seconds and upserts them into Salesforce. I have two pollers that run independently from one another that create custom sObjects of type Event and type Person. Event has a foreign-key to Person in the internal database and that's reflected on their sObjects via a lookup, and a Person can have multiple Events associated with him. There's a workflow within the internal database system that creates a new Event and Person simultaneously, and the integration app pollers pick up both of these and upsert them into Salesforce in a non-deterministic order.



My goal is to set the Person lookup on the Event sObject, taking into account that the records may come in out of order (a Person may be inserted before an Event, or an Event may be inserted before a Person). To handle this, I set up two triggers—one on Event and one on Person—that look to ensure that the lookup will always be set. The Event trigger takes the external ID of the Person that lives on the Event and tries to find matching Persons to set the lookup. The Person trigger finds all Events that contain the external ID of that Person and whose Person lookup is null and tries to set the lookup on the Events.



Because the records are inserted very near to each other (often within a few milliseconds), sometimes neither trigger is able to locate the records it needs (verified by placing log statements and seeing that the queries return no results). Both triggers run after insert, but I'm assuming because their execution happens pre-commit, if the trigger execution overlaps, then there's a chance that both triggers can effectively be unaware that the records they expect exist?



  1. What can I do here? Is there a way to run all this logic post-commit?

  2. Do triggers execute concurrently? Is there anyway to run them sequentially?









share|improve this question























  • Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
    – Pranay Jaiswal
    Nov 12 '18 at 19:58










  • Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
    – zed593
    Nov 12 '18 at 20:09










  • I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
    – Pranay Jaiswal
    Nov 12 '18 at 20:26










  • I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
    – Pranay Jaiswal
    Nov 12 '18 at 20:29















2














I have an integration app that polls records of different types from an internal database every few seconds and upserts them into Salesforce. I have two pollers that run independently from one another that create custom sObjects of type Event and type Person. Event has a foreign-key to Person in the internal database and that's reflected on their sObjects via a lookup, and a Person can have multiple Events associated with him. There's a workflow within the internal database system that creates a new Event and Person simultaneously, and the integration app pollers pick up both of these and upsert them into Salesforce in a non-deterministic order.



My goal is to set the Person lookup on the Event sObject, taking into account that the records may come in out of order (a Person may be inserted before an Event, or an Event may be inserted before a Person). To handle this, I set up two triggers—one on Event and one on Person—that look to ensure that the lookup will always be set. The Event trigger takes the external ID of the Person that lives on the Event and tries to find matching Persons to set the lookup. The Person trigger finds all Events that contain the external ID of that Person and whose Person lookup is null and tries to set the lookup on the Events.



Because the records are inserted very near to each other (often within a few milliseconds), sometimes neither trigger is able to locate the records it needs (verified by placing log statements and seeing that the queries return no results). Both triggers run after insert, but I'm assuming because their execution happens pre-commit, if the trigger execution overlaps, then there's a chance that both triggers can effectively be unaware that the records they expect exist?



  1. What can I do here? Is there a way to run all this logic post-commit?

  2. Do triggers execute concurrently? Is there anyway to run them sequentially?









share|improve this question























  • Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
    – Pranay Jaiswal
    Nov 12 '18 at 19:58










  • Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
    – zed593
    Nov 12 '18 at 20:09










  • I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
    – Pranay Jaiswal
    Nov 12 '18 at 20:26










  • I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
    – Pranay Jaiswal
    Nov 12 '18 at 20:29













2












2








2







I have an integration app that polls records of different types from an internal database every few seconds and upserts them into Salesforce. I have two pollers that run independently from one another that create custom sObjects of type Event and type Person. Event has a foreign-key to Person in the internal database and that's reflected on their sObjects via a lookup, and a Person can have multiple Events associated with him. There's a workflow within the internal database system that creates a new Event and Person simultaneously, and the integration app pollers pick up both of these and upsert them into Salesforce in a non-deterministic order.



My goal is to set the Person lookup on the Event sObject, taking into account that the records may come in out of order (a Person may be inserted before an Event, or an Event may be inserted before a Person). To handle this, I set up two triggers—one on Event and one on Person—that look to ensure that the lookup will always be set. The Event trigger takes the external ID of the Person that lives on the Event and tries to find matching Persons to set the lookup. The Person trigger finds all Events that contain the external ID of that Person and whose Person lookup is null and tries to set the lookup on the Events.



Because the records are inserted very near to each other (often within a few milliseconds), sometimes neither trigger is able to locate the records it needs (verified by placing log statements and seeing that the queries return no results). Both triggers run after insert, but I'm assuming because their execution happens pre-commit, if the trigger execution overlaps, then there's a chance that both triggers can effectively be unaware that the records they expect exist?



  1. What can I do here? Is there a way to run all this logic post-commit?

  2. Do triggers execute concurrently? Is there anyway to run them sequentially?









share|improve this question















I have an integration app that polls records of different types from an internal database every few seconds and upserts them into Salesforce. I have two pollers that run independently from one another that create custom sObjects of type Event and type Person. Event has a foreign-key to Person in the internal database and that's reflected on their sObjects via a lookup, and a Person can have multiple Events associated with him. There's a workflow within the internal database system that creates a new Event and Person simultaneously, and the integration app pollers pick up both of these and upsert them into Salesforce in a non-deterministic order.



My goal is to set the Person lookup on the Event sObject, taking into account that the records may come in out of order (a Person may be inserted before an Event, or an Event may be inserted before a Person). To handle this, I set up two triggers—one on Event and one on Person—that look to ensure that the lookup will always be set. The Event trigger takes the external ID of the Person that lives on the Event and tries to find matching Persons to set the lookup. The Person trigger finds all Events that contain the external ID of that Person and whose Person lookup is null and tries to set the lookup on the Events.



Because the records are inserted very near to each other (often within a few milliseconds), sometimes neither trigger is able to locate the records it needs (verified by placing log statements and seeing that the queries return no results). Both triggers run after insert, but I'm assuming because their execution happens pre-commit, if the trigger execution overlaps, then there's a chance that both triggers can effectively be unaware that the records they expect exist?



  1. What can I do here? Is there a way to run all this logic post-commit?

  2. Do triggers execute concurrently? Is there anyway to run them sequentially?






apex trigger dml before-trigger after-trigger






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 20:44







zed593

















asked Nov 12 '18 at 19:37









zed593zed593

204




204











  • Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
    – Pranay Jaiswal
    Nov 12 '18 at 19:58










  • Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
    – zed593
    Nov 12 '18 at 20:09










  • I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
    – Pranay Jaiswal
    Nov 12 '18 at 20:26










  • I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
    – Pranay Jaiswal
    Nov 12 '18 at 20:29
















  • Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
    – Pranay Jaiswal
    Nov 12 '18 at 19:58










  • Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
    – zed593
    Nov 12 '18 at 20:09










  • I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
    – Pranay Jaiswal
    Nov 12 '18 at 20:26










  • I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
    – Pranay Jaiswal
    Nov 12 '18 at 20:29















Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
– Pranay Jaiswal
Nov 12 '18 at 19:58




Cant the 3rd part system retry? Sometimes I have seen records inserted are not available for 1-2 seconds.
– Pranay Jaiswal
Nov 12 '18 at 19:58












Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
– zed593
Nov 12 '18 at 20:09




Retrying is not an option. The pollers don't work that way, and it doesn't make sense to anyway since the records do get inserted. The issue is on the Salesforce side.
– zed593
Nov 12 '18 at 20:09












I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
– Pranay Jaiswal
Nov 12 '18 at 20:26




I don't think it's salesforce issue, bring any system with this level of concurrency it will be same everywhere
– Pranay Jaiswal
Nov 12 '18 at 20:26












I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
– Pranay Jaiswal
Nov 12 '18 at 20:29




I belive it's one of such occasions where one might have to introduce a Middleware in between that can queue jobs.
– Pranay Jaiswal
Nov 12 '18 at 20:29










1 Answer
1






active

oldest

votes


















4















What can I do here? Is there a way to run all this logic post-commit?




You do need to do at least some of this asynchronously, because any other technique is going to end up in deadlock or missing records. In both triggers, build a list of unique identifiers, then pass it in to a Queueable:



public class ResolveExternals implements Queueable 
String externals;
public ResolveExternals(String values)
externals = values;

public void execute(QueueableContext context)
Event events = [SELECT ... FROM Event WHERE External_Id__c = :externals FOR UPDATE];
Contact contacts = [SELECT ... FROM Contact WHERE External_Id__c = :externals FOR UPDATE];
// match results




In each trigger:



String externals = new String[0];
for(... record: Trigger.new)
externals.add(record.External_Id__c);

System.enqueueJob(new ResolveExternals(externals));


The trick here is that FOR UPDATE will wait for a few seconds for either object that might be in-flight (but they must have been started). Since it's asynchronous, even triggers fired within milliseconds of each other should be just fine.



Or, as a minor adjustment, allow one or the other to use FOR UPDATE (but not both, to avoid deadlocks), and make the other asynchronous. This should keep database contention down but use up less daily limits (250,000 asynchronous calls/day).




Do triggers execute concurrently? Is there anyway to run them sequentially?




Yes, they run concurrently. There are some techniques that you could try, but it would still be easy to accidentally construct deadlocks, and you'll cause massive database contention under heavy loads. You'd have to test it to make sure that it doesn't start causing cascading failures.



As long as the locks are always acquired in the same order, you should be just fine. Also read more about avoiding deadlocks.






share|improve this answer
















  • 1




    This is a solid answer. Or you can make use of @future
    – crc442
    Nov 12 '18 at 20:34










  • Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
    – zed593
    Nov 12 '18 at 21:06






  • 1




    @zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
    – sfdcfox
    Nov 12 '18 at 21:10










  • What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
    – zed593
    Nov 12 '18 at 21:13






  • 1




    @zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
    – sfdcfox
    Nov 12 '18 at 21:21










Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "459"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f239100%2ffailure-setting-lookups-in-triggers-when-upserting-multiple-records-of-different%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









4















What can I do here? Is there a way to run all this logic post-commit?




You do need to do at least some of this asynchronously, because any other technique is going to end up in deadlock or missing records. In both triggers, build a list of unique identifiers, then pass it in to a Queueable:



public class ResolveExternals implements Queueable 
String externals;
public ResolveExternals(String values)
externals = values;

public void execute(QueueableContext context)
Event events = [SELECT ... FROM Event WHERE External_Id__c = :externals FOR UPDATE];
Contact contacts = [SELECT ... FROM Contact WHERE External_Id__c = :externals FOR UPDATE];
// match results




In each trigger:



String externals = new String[0];
for(... record: Trigger.new)
externals.add(record.External_Id__c);

System.enqueueJob(new ResolveExternals(externals));


The trick here is that FOR UPDATE will wait for a few seconds for either object that might be in-flight (but they must have been started). Since it's asynchronous, even triggers fired within milliseconds of each other should be just fine.



Or, as a minor adjustment, allow one or the other to use FOR UPDATE (but not both, to avoid deadlocks), and make the other asynchronous. This should keep database contention down but use up less daily limits (250,000 asynchronous calls/day).




Do triggers execute concurrently? Is there anyway to run them sequentially?




Yes, they run concurrently. There are some techniques that you could try, but it would still be easy to accidentally construct deadlocks, and you'll cause massive database contention under heavy loads. You'd have to test it to make sure that it doesn't start causing cascading failures.



As long as the locks are always acquired in the same order, you should be just fine. Also read more about avoiding deadlocks.






share|improve this answer
















  • 1




    This is a solid answer. Or you can make use of @future
    – crc442
    Nov 12 '18 at 20:34










  • Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
    – zed593
    Nov 12 '18 at 21:06






  • 1




    @zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
    – sfdcfox
    Nov 12 '18 at 21:10










  • What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
    – zed593
    Nov 12 '18 at 21:13






  • 1




    @zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
    – sfdcfox
    Nov 12 '18 at 21:21















4















What can I do here? Is there a way to run all this logic post-commit?




You do need to do at least some of this asynchronously, because any other technique is going to end up in deadlock or missing records. In both triggers, build a list of unique identifiers, then pass it in to a Queueable:



public class ResolveExternals implements Queueable 
String externals;
public ResolveExternals(String values)
externals = values;

public void execute(QueueableContext context)
Event events = [SELECT ... FROM Event WHERE External_Id__c = :externals FOR UPDATE];
Contact contacts = [SELECT ... FROM Contact WHERE External_Id__c = :externals FOR UPDATE];
// match results




In each trigger:



String externals = new String[0];
for(... record: Trigger.new)
externals.add(record.External_Id__c);

System.enqueueJob(new ResolveExternals(externals));


The trick here is that FOR UPDATE will wait for a few seconds for either object that might be in-flight (but they must have been started). Since it's asynchronous, even triggers fired within milliseconds of each other should be just fine.



Or, as a minor adjustment, allow one or the other to use FOR UPDATE (but not both, to avoid deadlocks), and make the other asynchronous. This should keep database contention down but use up less daily limits (250,000 asynchronous calls/day).




Do triggers execute concurrently? Is there anyway to run them sequentially?




Yes, they run concurrently. There are some techniques that you could try, but it would still be easy to accidentally construct deadlocks, and you'll cause massive database contention under heavy loads. You'd have to test it to make sure that it doesn't start causing cascading failures.



As long as the locks are always acquired in the same order, you should be just fine. Also read more about avoiding deadlocks.






share|improve this answer
















  • 1




    This is a solid answer. Or you can make use of @future
    – crc442
    Nov 12 '18 at 20:34










  • Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
    – zed593
    Nov 12 '18 at 21:06






  • 1




    @zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
    – sfdcfox
    Nov 12 '18 at 21:10










  • What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
    – zed593
    Nov 12 '18 at 21:13






  • 1




    @zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
    – sfdcfox
    Nov 12 '18 at 21:21













4












4








4







What can I do here? Is there a way to run all this logic post-commit?




You do need to do at least some of this asynchronously, because any other technique is going to end up in deadlock or missing records. In both triggers, build a list of unique identifiers, then pass it in to a Queueable:



public class ResolveExternals implements Queueable 
String externals;
public ResolveExternals(String values)
externals = values;

public void execute(QueueableContext context)
Event events = [SELECT ... FROM Event WHERE External_Id__c = :externals FOR UPDATE];
Contact contacts = [SELECT ... FROM Contact WHERE External_Id__c = :externals FOR UPDATE];
// match results




In each trigger:



String externals = new String[0];
for(... record: Trigger.new)
externals.add(record.External_Id__c);

System.enqueueJob(new ResolveExternals(externals));


The trick here is that FOR UPDATE will wait for a few seconds for either object that might be in-flight (but they must have been started). Since it's asynchronous, even triggers fired within milliseconds of each other should be just fine.



Or, as a minor adjustment, allow one or the other to use FOR UPDATE (but not both, to avoid deadlocks), and make the other asynchronous. This should keep database contention down but use up less daily limits (250,000 asynchronous calls/day).




Do triggers execute concurrently? Is there anyway to run them sequentially?




Yes, they run concurrently. There are some techniques that you could try, but it would still be easy to accidentally construct deadlocks, and you'll cause massive database contention under heavy loads. You'd have to test it to make sure that it doesn't start causing cascading failures.



As long as the locks are always acquired in the same order, you should be just fine. Also read more about avoiding deadlocks.






share|improve this answer













What can I do here? Is there a way to run all this logic post-commit?




You do need to do at least some of this asynchronously, because any other technique is going to end up in deadlock or missing records. In both triggers, build a list of unique identifiers, then pass it in to a Queueable:



public class ResolveExternals implements Queueable 
String externals;
public ResolveExternals(String values)
externals = values;

public void execute(QueueableContext context)
Event events = [SELECT ... FROM Event WHERE External_Id__c = :externals FOR UPDATE];
Contact contacts = [SELECT ... FROM Contact WHERE External_Id__c = :externals FOR UPDATE];
// match results




In each trigger:



String externals = new String[0];
for(... record: Trigger.new)
externals.add(record.External_Id__c);

System.enqueueJob(new ResolveExternals(externals));


The trick here is that FOR UPDATE will wait for a few seconds for either object that might be in-flight (but they must have been started). Since it's asynchronous, even triggers fired within milliseconds of each other should be just fine.



Or, as a minor adjustment, allow one or the other to use FOR UPDATE (but not both, to avoid deadlocks), and make the other asynchronous. This should keep database contention down but use up less daily limits (250,000 asynchronous calls/day).




Do triggers execute concurrently? Is there anyway to run them sequentially?




Yes, they run concurrently. There are some techniques that you could try, but it would still be easy to accidentally construct deadlocks, and you'll cause massive database contention under heavy loads. You'd have to test it to make sure that it doesn't start causing cascading failures.



As long as the locks are always acquired in the same order, you should be just fine. Also read more about avoiding deadlocks.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 12 '18 at 20:29









sfdcfoxsfdcfox

248k11191426




248k11191426







  • 1




    This is a solid answer. Or you can make use of @future
    – crc442
    Nov 12 '18 at 20:34










  • Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
    – zed593
    Nov 12 '18 at 21:06






  • 1




    @zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
    – sfdcfox
    Nov 12 '18 at 21:10










  • What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
    – zed593
    Nov 12 '18 at 21:13






  • 1




    @zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
    – sfdcfox
    Nov 12 '18 at 21:21












  • 1




    This is a solid answer. Or you can make use of @future
    – crc442
    Nov 12 '18 at 20:34










  • Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
    – zed593
    Nov 12 '18 at 21:06






  • 1




    @zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
    – sfdcfox
    Nov 12 '18 at 21:10










  • What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
    – zed593
    Nov 12 '18 at 21:13






  • 1




    @zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
    – sfdcfox
    Nov 12 '18 at 21:21







1




1




This is a solid answer. Or you can make use of @future
– crc442
Nov 12 '18 at 20:34




This is a solid answer. Or you can make use of @future
– crc442
Nov 12 '18 at 20:34












Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
– zed593
Nov 12 '18 at 21:06




Thank you, appreciate the detailed response. If I were able to guarantee order, would I be able to do it differently? Is there any way to operate on the same batch of disparate records?
– zed593
Nov 12 '18 at 21:06




1




1




@zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
– sfdcfox
Nov 12 '18 at 21:10




@zed593 Each trigger operates on exactly one object. That said, if you could guarantee the order, then you'd only have to worry about one trigger at most (or, optionally, use external ID relationships and skip the queries entirely).
– sfdcfox
Nov 12 '18 at 21:10












What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
– zed593
Nov 12 '18 at 21:13




What do you mean by "external ID relationships" exactly? Is there some automatic way of creating relationships from external ID fields?
– zed593
Nov 12 '18 at 21:13




1




1




@zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
– sfdcfox
Nov 12 '18 at 21:21




@zed593 There's a ton of awesome options in the API; the composite API, the sobject tree API, the SOAP API, normal REST API calls. Being able to guarantee order would have you a lot of trouble.
– sfdcfox
Nov 12 '18 at 21:21

















draft saved

draft discarded
















































Thanks for contributing an answer to Salesforce Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f239100%2ffailure-setting-lookups-in-triggers-when-upserting-multiple-records-of-different%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3