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.