[SalesForce] Can an ID in a lookup field ever be invalid? Anywhere

Salesforce documentation gives the following rules for non-mandatory lookup fields:

  • When the target is deleted, by default fields that reference it are set to null.
  • You can tell it to prevent deletion of an object if it is referenced by lookups.
  • If you phone Salesforce you can be allowed to set up cascade delete.

The documentation is not clear about mandatory lookup fields, but I'd hope that Salesforce maintains the constraint by preventing deletion.

It looks as if it is impossible for an ID read from a lookup field to not resolve to a real record, but code I have inherited seems to want to check this by performing a SOQL query to see if the record exists. This costs SOQL governor.

Before I delete this code, is there any situation where it may be needed? When does Salesforce perform these constraint checks? Is it possible for the target to be deleted in the same transaction and the result to be wrong in a trigger? Salesforce performs triggers at the point of the DML operation, so I could only see this happening if either

  • The Lookup is a lookup to self
  • Code in the trigger performs the delete

We'd not do the latter. Maybe some other person will, but it sounds unlikely.

So is there something I'm missing? I assume Salesforce transactions see the state of the database including all changes already made in the transaction, so the code is not trying to determine the state of the system before the transaction.

Best Answer

It is possible that I can read an ID from a field, and when querying for the item with the given ID I find no result. This will happen when Sharing Rules prevent the user seeing the item and the code is running "With Sharing".

The Sharing-ness of the code switches depending on the call tree, so as code enters a class that is marked with or without sharing permissions change. The permission does not change when execution enters a class that does not have a with or without sharing declaration.

Code generally runs Without Sharing, so this problem is only likely to occur if "With Sharing" has been explicitly turned on somewhere. (Or if the user calls anonymous apex). Trigger code starts Without Sharing, even if the code which called the DML was With Sharing.

For Sharing see Salesforce documentation on Sharing keywords.