In this blog post, we are going to go over a few topics like the basics of SOQL relationship query, what a polymorphic field is, where it is used in Salesforce, and how we use it in Apex.
In our beloved query language that Salesforce has kindly provided us with, SOQL (Salesforce Object Query Language) there are several ways to traverse the different types of relationships through the use of a lookup or master-detail relationship. For example, from child-to-parent we would do something like this to get some Account information from a Contact:
This is done by simply using the dot notation, it simply goes up the relationship tree, referencing the parent object when we query the child object. It can go up to most 5 levels of the relationship tree, and fields then can be easily accessed like the example below:
From parent to child we would do something like this to gather all the related Contacts of an Account:
We would have a sub-query for the child object with the FROM being the relationship name, which in this case is Contacts. This type of query goes down the relationship tree and at most could only go down 1 level, meaning that we could access the information in the related Contacts but not the information of the object that is related to the Contacts further down the relationship tree. To access the contacts information, we would need to do something like this:
When using these types of queries in Salesforce/Apex we sometimes run across lookup relationship fields with weird names such as WhoId, WhatId, ParentRecordId, etc. The easiest way to see this would be on the Task object, where we could see that it has a lookup type field with the name Related To
And if we go to Workbench to see the details of this field, we could then see that it is a Polymorphic field that is referencing 93 objects (this depends on how your org is setup), and another field of name Name with API name WhoId which reference Contact and Lead object.
So, what is a polymorphic? A quick search on Google would explain that it means occurring in several different forms, in particular with reference to species or genetic variation. For our context of Salesforce Computing, it would simply mean a lookup field that is related to several different types of objects. For example, if we want to get the related Work Order of a Task, in older Salesforce API versions (version less than 46.0) to get this information we would have to do this:
We first have to query the Task and get the WhatId, which is the Work Order Id then use this Id to get the information of the Work Order for the related Asset Id or Case Id. This would take two SOQL calls to get the information required and further use up the SOQL limits/resources and most important of all, doesn’t look as neat.
Knowing this issue, Salesforce then trialed something called Polymorphic Query using the TYPEOF keyword. This feature was first piloted in API version 26.0 but was only available for Developer Accounts. It was released for General Adoption alongside the release of Summer ’19 of API version 46.0. To use this new TYPEOF query construct we need these keywords: TYPEOF-WHEN-THEN-END.
• TYPEOF needs to be followed by a polymorphic relationship name.
• WHEN SObject type, followed by the fields you want from that object.
• THEN fields that we need the information of and traversing further up an object hierarchy are just fine.
• END to explicitly tell Salesforce when the TYPEOF clause ends.
For the example we have seen earlier, we could then refactor it to this single query:
In simple terms, the query is getting the Tasks that are related to a Work Order. The sub-query TYPEOF is simply saying if What we are getting is of the type of a Work Order, then grab the information from the fields Id, Asset Id, Asset Name and Case Id. To get information on different objects we just need to add another WHEN-THEN scenario, for example:
It’s all good on how to query the required information, but how would we get to the actual field value using Apex? If we need to access the referenced object in a polymorphic relationship, then we need to use the instanceof keyword to determine the object type. For the example above, we would simply do:
If we access the Work Order Number field using the dot notation like “myTask.What.WorkOrderNumber”, then the compiler will complain as Work Order Number is not an attribute of that Polymorphic object.
All in all, if you ever run into a scenario where you need to query a related object that is a polymorphic field, then you should use the TYPEOF query construct. Thanks to Salesforce’s new query construct TYPEOF we can write queries that are more dynamic, easier to read/understand and keep SOQL limits down low.