[SalesForce] From Parent ID, dynamically derive child’s lookup field name/token

I'm trying to save a new record dynamically, but I'm having a problem with a lookup field. For instance, I'm able to get the parent object with the id.

Id relatedID = '<someId>';
SObjectType parentObj = relatedID.getSobjectType();

But let's say as ab example, parentObj = Supervisor__c and the object I need to insert is Employee__c. The field name on for the lookup on Employee__c to Supervisor__c is called Manager__c (which I want to get and set dynamically). How can I get and set that field name with an insert? I know getReferencedTo() will return the object, but not sure how to go from the object to the field set it with dynamic dml.

This works, but it's rather ugly and I'm sure I'm missing something and it can be simplified.

Id relatedId = '<some id>';
SObjectType supervisorType = relatedID.getSobjectType();
SObjectType employeeType = Schema.getGlobalDescribe().get('Employee__c');
SObject employee = employeeType.newSObject();

Schema.DescribeSObjectResult objSchema = Employee__c.sObjectType.getDescribe();
Map<String, Schema.SObjectField> fieldMap = objSchema.fields.getMap();
for(Schema.SObjectField sfield : fieldMap.Values()) {
    if (sfield.getDescribe().getReferenceTo().size() > 0) {
          if (sfield.getDescribe().getReferenceTo()[0] == supervisorType) {
              employee.put(sfield.getDescribe().getName(), relatedId);
              System.debug(story);
              break;
          }
    }
}

Best Answer

As I understand the question, for a given child sObject and a given parent (lookup) object's ID, how do you locate the child object's lookup field name or token?

In your example,

Employee__c has several lookup fields to several parents. If you have some parentId, you can easily get the SObjectType of the parent with parentId.getSobjectType() but what is the corresponding fieldname/token in Employee__c?

There's no way to derive this dynamically from the describe information reliably because a given child SObject can have multiple lookup fields to the same parent SObject.

A classic example of this in Opportunity wherein I often see folks adding lookup fields to key Contacts such as BillToContact__c and ShipToContact__c (rather than using OpportunityContactRole which has some challenges for other reasons)

If you had an Opportunity and an ID of some Contact, which of the two Opportunity lookup fields to Contact do you try and set with the someContactId?

You can't, because it is the relationship name that tells you which lookup field to use and the relationship name can't be derived from someContactId

As you stated in your comment, in a limited application wherein you guaranteed that there were never multiple lookup fields to the same parent, you could build a map of:

map<SobjectType,SobjectField> parentTypeToChildFldTokenMap

and then you could look up the field token of the child object with:

SobjectField fldToken = parentTypeToChildFldTokenMap.get(someParentId.getSObjectType());

Otherwise, the application needs to know which relationship the someParentId participates in to ascertain the child fieldToken. Then, you would go to the parent's Describe result and loop through the ChildRelationships looking for a match on relationshipname. The ChildRelationship object contains the fieldtoken of the child lookup field.

Related Topic