[SalesForce] Upsert Detail object without external Id

I have two related objects (Master-Detail) A -> B (where B is child of A). In addition there is only one B for a parent A.

I need to upsert the B object and I only have the A.Id and other fields of B. But not the B.Id.

I was trying this:

List<B__c> listToUpsert = new List<B__c>();
for(BObject dataB: listOfDataB){
   B__c b = new B__c();
   b.parentA_Id__c = dataB.parentA_id;
   b.otherField__c = dataB.otherField;   

} 

upsert listToUpsert;

This works, but is always inserting new records.

Since I have not chance to know the previous B.id or generate an external Id on B relation to A in the original data to upsert. The only workaround that I think is to query first the existing B then update those A.id and finally upsert.

Sample

//build a set of B.client ids
Set<Id> existingBsIds = new Set<Id>();
for(BObject b: listOfDataB){
    existingBsIds.add(b.parentA_Id__c);
}
//get existing
Map<Id, B__c> existingBsMap = new Map<Id, B__c>();
//build existing map
for(B__c b:[SELECT id,parentA_Id__c FROM  B__c WHERE parentA_Id__c in :existingBsIds]){
    existingBsMap.put(b.parentA_Id__c, b.id);
}

//update id to upsert
B__c b; 
for(BObject dataB: listOfDataB){
    b = new B__c(id = existingBsMap.get(dataB.parentA_Id));
    b.parentA_Id__c = dataB.parentA_id;
    b.otherField__c = dataB.otherField; 
    BsToUpsert.add(b);
}

upsert BsToUpsert;

Question

Is there other better approach to upsert a child object using the parent id as external Id?

Update

Another idea could be to have an extra text field as external Id, and fill it with the parentA_id using a trigger.

Best Answer

If I understand correctly, you have a list ? If this is the case, what happens if you cast the list to a map? This is going to be highly dependent on the context of execution but this might help.

Map<Id,bObj__c> mapOfAwesome = new Map<Id, bObj__c>(bObjectList);

Again, not knowing the context of execution this could be another red herring.

Related Topic