11

Question

I know that it is possible to update a generic of List<SObject>, But what is the best approach to generate that list without knowing the SObjectType, only the ids ?

Sample:

 List<SObject> l = new List<SObject>();

 SObject o1 = new SObject(id='xxxxxx'); //this Id could be an Account
 o1.Name = 'Test';
 l.add(o1);


 SObject o2 = new SObject(id='xxxxxx'); //this Id could be a Custom
 o2.Name = 'Test' 
 l.add(o2); 

 //this is possible
 update l;

Unfortunately, SObject constructor doesn't allow id as parameter.

Backgound:

I'm trying to make a generic WS which will receive a list of objects to update( or upsert). The received object could by any type.

WS Request sample:

  [
   {id:'xxxxx',Name:'Test'},
   {id:'yyyyy',Name:'Test 2'},
   {id:'zzzzz',Name:'Test 3'}
  ]

The id attribute cloud be from any SObject.( I know the extra attr to update always exist).

Thanks in advance for your time.

  • What exactly is the web service receiving? – Mike Chale Oct 9 '13 at 18:36
  • @MikeChale I've updated my question adding a request sample – Martin Borthiry Oct 9 '13 at 18:43
  • Couldnt you use the ID key prefix to determine what the type of SObject was? – Chris Duncombe Oct 9 '13 at 19:12
  • I though so, looks like @amatorVitae used this prefix method. Beat me to typing it out lol – Chris Duncombe Oct 9 '13 at 19:14
17

Once you have the sObjectType you should be able to construct the sObject instance using the sObjectType.newSObject(ID Id) method. You can get the sObjectType from the Id using the Id.getSObjectType() method;

Map<Id, String> idsToUpdate = new Map<Id, String>();

// Put the Id's and associated name values in the map

List<SObject> sObjectsToUpdate = new List<SObject>();

for (Id idToUpdate : idsToUpdate.keySet()) {
    SObject o1 = idToUpdate.getSObjectType().newSObject(idToUpdate);
    // Set the Name field dynamically
    o1.put('Name', idsToUpdate.get(idToUpdate));
    sObjectsToUpdate.add(o1);
}

update sObjectsToUpdate;
  • Incredible answer, This is exactly what I was looking for. – Martin Borthiry Oct 9 '13 at 22:21
  • When I try this sample code, I'm getting Variable does not exist: Name. Have any idea why? – Brane Oct 8 '18 at 12:57
  • @user3850805 I've changed the code to use a dynamic put to set the Name field. – Daniel Ballinger Oct 8 '18 at 20:29
5

Here's a link to a post that I think answers your question: Infering sObject Type from Id or collection of Id's

Essentially, the solution entails:

  1. Pulling the sObject "prefix" (the first 3 characters) from the id you receive
  2. Get the sObjectType so you can cast your objects as the corresponding sObject (or list<yourSobject__c>)
  3. Upsert the typed-records

Link to SF Docs


Here's a Utility Method I wrote that writes a query to select ALL fields from an sObject by only giving the string value of the Object Name. It exemplifies finding an sObject's metadata (in this case, its fields).

public static string FormatFieldsForQuery(string objectName,string prefix){
    if(string.isNotBlank(prefix)){
        if(prefix.endsWith('__c'))
            prefix=prefix.replace('__c','__r.');   
        if(!prefix.endsWith('.'))
            prefix+='.';
    }
    string fields = '';
    sObjectType objectType=Schema.getGlobalDescribe().get(objectName);
    if(objectType==null)
        return fields;
    for(string f :objectType.getDescribe().fields.getMap().keySet())
        fields+=prefix+f+',';
    return fields.removeEnd(',');  
}//END FormatFieldsForQuery(string objectName,string prefix)
  • Based on @DanielBallinger comment , your answer and @ca_peterson answer, I think this is possible: Sobject o1 = Schema.getGlobalDescribe().get(myId.getSObjectType().getDescribe().getName()).newSObject(myId); , isn't ?.... One line will solve my problem, sounds awsome – Martin Borthiry Oct 9 '13 at 19:34
  • @MartinBorthiry Sorry, I deleted my comment as I wanted to expand on it as a separate answer. IMHO amatorVitae still deserves the credit for getting the answer. – Daniel Ballinger Oct 9 '13 at 19:41
  • @amatorVitae thanks for this approach, It was the base for the best solution. My up vote here – Martin Borthiry Oct 9 '13 at 22:23

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.