I'm trying to make something that reads csv's and imports the data for our users, but SF ids for the lookups on the Contact are cumbersome for them as they already know the External Ids of the object related.

For Example:

We have a Country_of_Domicile__c object which has an external Id which might be for example 'USA' or 'ENG'.

The Contact has a lookup to this object on the Country_of_Domicile__c field.

How can I, only knowing the external ID of the record, attach it to the contact that is being Upserted.

Example non-working code below of what i'm trying to achieve:

string relatedObjectName = 'Country_of_Domicile__c';

sObject relatedsObj = Schema.getGlobalDescribe().get(relatedObjectName ).newSObject();



Obviously I know i can query for this data and use a Map to put the ID directly but i'd rather not given then limits and loops, and also not knowing how many queries i'll need at run-time. Is this possible without any Queries?


The above doc says what i'm trying to do should be more-or-less possible but it explicitly declares the type of the Object and again I'd like to be able to avoid that to have it more flexible.

Edit: Marking Adrian's answer as correct as it was accurate I just want to add the following block of code that is hopefully a bit more generic:

string relatedObjectR = 'COD__r'; //field name on contact that looks up country with the __c replaced with __r
string relatedObjectC = 'Country_of_Domicile__c' //object name 
string extIdField = 'Code__c' // External Id field on the related object
string data = 'ENG'; //Country's external Id
sObject relatedsObj = Schema.getGlobalDescribe().get(relatedObjectC).newSObject(); //instantiates lookup object
relatedsObj.put(extIdField,data); //sets the External Id of that object
contact.putSObject(relatedObjectR, relatedsObj); //puts the value onto the correct field on the contact: 'COD_c'
  • Possible duplicate: salesforce.stackexchange.com/q/133556/2995
    – Adrian Larson
    Feb 23, 2017 at 19:11
  • This works when you know that you're making an Account and Contact specifically but is it possible with a dynamic sObject? Feb 23, 2017 at 22:57
  • Why does it need to be dynamic? The situation you describe indicates you already know what type of object it is.
    – Adrian Larson
    Feb 23, 2017 at 23:15
  • Actually i think that does work - is it just the exact object name that ends in __r instead of __c? Does that sometimes change? Feb 23, 2017 at 23:18
  • I know it in this example but not in most cases this is just an example for the inbound object name Feb 23, 2017 at 23:22

1 Answer 1


You need to make sure that you use the correct relationship name. Here is a simple example that proves this functionality works just fine with a generic SObject record.

SObjectField lookup = Contact.AccountId, external = Account.Counsyl_Id__c;
SObjectType childType = Contact.sObjectType, parentType = Account.sObjectType;
String relationshipName = lookup.getDescribe().getRelationshipName();
Map<SObjectField, Object> requiredFields = new Map<SObjectField, Object>
    Contact.LastName => 'Doe'

SObject parent = parentType.newSObject();
parent.put(external, '12345');

SObject child = childType.newSObject();
child.putSObject(relationshipName, parent);
for (SObjectField field : requiredFields.keySet())
    child.put(field, requiredFields.get(field));
insert child;

Note that you need to make sure to use the relationship name in the putSObject call, not the field name. With Contact.AccountId, that correct value would be Account. With a custom lookup, it would be Lookup__r rather than Lookup__c.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .