0

Updated my question:

Scenario:I am making certain changes in an opportunity record and clicking save. This causes trigger to execute and this trigger is executed recursively 3-4 times. Now say I have a class "C" with method "M". In this class "C",there is a private static List of records "L" which is used in method "M" .

--->1st call of method "M" due to 1st call of trigger:we fetch a field "Name" of object "Object1" placed at 0th position in List "L" and its field in a variable as:

String var= L[0].Name

Value of var="ABC"

After this execution a DML operation somewhere else in code changes value of Object1.Name to "XYZ"

--->2nd call of method "M" due to next recursive call of same trigger: String var= L[0].Name

Value of var=?

Now in this case, what will be the value of var?

  • list will have the values but if you try to query records based on list ids then it will be give you zero result. – Ratan Paul May 4 '16 at 8:43
  • Perhaps some pseudocode or a trimmed-down version of you code would be easier to follow. – mkorman May 5 '16 at 10:09
  • I have updated my answer – mkorman May 5 '16 at 10:13
0

I think you have a concurrency issue. I'm assuming this is your situation:

  • You have an execution context (let's call it A), where you query the database and get a list of records
  • While Context A is still running, another execution context (let's call it B), deletes a record from the database (one of the records that is kept in memory in A).

If this is the case, your record will remain in memory in context A. It will not be replaced by a null. But at this point, context A is stale (its in-memory representation does not match the database state) because of concurrency. You can reference the deleted record and display its information. However, any attempt to persist it (DML) will fail.

However, if context A ends the execution, and you call the same method again (let's say that the user clicks the same button that started A to begin with), you will have a new execution context (let's call it A') that runs after B has finished.

A' will not have a reference to the deleted object (it will not even be a null... the record will simply not be returned by the query).

Edit (after your question update):

  • I've just seen that your list (L) is static
  • Since it's a trigger calling a method and then the trigger recursively, everything happens in the same execution context (unless you're using futures/async)
  • In either case, if you don't requery your list whenever you enter your method, you'll have stale information (ie: L[0].Name will still be "ABC"). If you requery it, then it will probably be something else.

On a different note, unless there is a very good reason for this, recursive triggers are a bad idea. They often cause more harm than good. I would try to reengineer your code to avoid the recursivity unless you really know what you're doing. There's a good resource on how to avoid recursive triggers here.

  • Thanks for that! yes that is almost my issue. Its just that the method is called multiple times in same transaction/execution flow due to recursion happening in trigger. In this case, so I am not calling any method again by CLICKING any any button, it is called automatically through trigger recursive call. So in this case, would your above explanation hold same? Thanks in advance!! – Sarang May 4 '16 at 12:36
  • You would need to explain how it works in detail. If the method is called by the trigger, unless it's in a future or asynchronous method, then it is all happening in the same context as the trigger. My guess is that if A' (second invocation of your method) is called by B (trigger), then A' will not see the record that B deleted. Please update your question with an exact flow of what calls what and then perhaps we can help – mkorman May 4 '16 at 13:03
  • updated my question – Sarang May 5 '16 at 5:04
  • Thanks a lot!!! Wanted to know just exactly that:) Regarding recursive trigger, there is a recursion handling mechanism, but yes, I will try to avoid to have recursive triggers – Sarang May 5 '16 at 10:15
2

If I understood your scenario correctly, below is my thought on this.

  • Your list of custom objects are in memory in your class scope while running the query.
  • When the trigger delete some record, that'll not real time reflects on the list.
  • Therefore in memory list will remain as it is (in memory level).

But if you try to perform a DML on the deleted record after running the trigger, an exception will be thrown 'Record is deleted' or something.

  • I do not want to performe DML on deleted record. I just want to use it in my code. Ex: I have a field in Record 'A' named 'flag' and this record in added in a list 'ListL'. Now a DML removes this record from DB. After this, I come across this list which contained this Record'A' and here I am trying to retreive flag and assign it to some other variable: String a=ListL.RecordA.flag In this case, what will be the value of String a? – Sarang May 4 '16 at 10:07
0

You can still access the deleted records by adding FOR ALL in to your query,without ALL tag , you will get exception , as ratan mentioned.

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.