0

In my logic I need to paste objects to list, and those objects will have same ids, but different other fields. Smth like this:

List<Contact> retreivedContacts = getContacts();
List<Contact> contactsToSend = new List<Contact>();
        for(Contact ct: retreivedContacts) {
            if(ct.isBilling) {
                Contact cnt = ct;
                cnt.Trade_Show_Main_Directory_Contact__c = false;
                contactsToSend.add(ct);
            }
            if(ct.isInternal) {
                Contact cnt = ct;
                cnt.Trade_Show_Main_Directory_Contact__c = false;
                contactsToSend.add(ct);
            }

        }

Maybe some solution exists to avoid exception 'Duplicate Id in list'.

1
  • 1
    You need to figure out which version of the sObject you want to keep and only include that. You cannot update an object with two different values for the same field or same object for that case. You have to decide which one you want to keep.
    – Eric
    Jul 20, 2017 at 15:13

2 Answers 2

0

There isn't any issue with storing multiple copies of an SObject in a List, at least not until you try to perform some DML on that List (as you've discovered).

That said, your code doesn't behave the way you think it does. The good news is that the way your code does behave will end up making things easier.

Let's take a look at a specific part of your code:

for(Contact ct: retreivedContacts) {
    if(ct.isBilling) {
        Contact cnt = ct;
        cnt.Trade_Show_Main_Directory_Contact__c = false;
        contactsToSend.add(ct);
    }
...
}

In this code, the Contact cnt = ct; line does not make a copy of the Contact represented by ct. Instead, it makes a new reference to the Contact represented by ct. (If you wanted a completely separate copy, you would need to use ct.clone()).

When you are working with a reference (as you are in this case), a change to a field of one of the references will cause that field to be changed on all references to that particular SObject.

So Contact cnt = ct; ends up doing very little. It can be removed completely without consequence. Furthermore, for(Contact ct :retrievedContacts) also stores a reference (not a separate copy) of each Contact from your retrievedContacts list in ct. Changing ct inside of the loop will change the value stored in the Contacts in retrievedContacts.

Given all of that, we can shorten your code (and also resolve the issue you were running into).

This code is functionally equivalent to the snippet you've provided.

List<Contact> retreivedContacts = getContacts();
// The line below is only necessary if you need to gather billing/internal contacts
//   specifically for other processing later in your code.
//List<Contact> contactsToSend = new List<Contact>();
for(Contact ct: retreivedContacts) {
    // Since you're updating the same field in both if blocks, we can consolidate them
    if(ct.isBilling || ct.isInternal) {
        // Since ct is a reference to an SObject in retrievedContacts, there's
        //   no need to create a separate Contact variable, nor is there a need
        //   to add ct to another list (unless you are doing specific processing
        //   for billing/internal contacts later on in your code).
        ct.Trade_Show_Main_Directory_Contact__c = false;

        // If you are going to add things to contactsToSend, it's best to try to
        //   only add it once.
        // If your logic isn't quite this simple, so that it can't easily be
        //   handled by a single 'if' block and you could possibly add the same 
        //   record to the list more than once, then a Map<Id, Contact> would
        //   be more appropriate to use (rather than a list).
        //contactsToSend.add(ct);
    }
}

// With the code you've provided us, this is all you would need to do to update
//   record values.
// update retrievedContacts;
0

Since you're always just setting one field, and to the same value, simply use a Map<Id, SObject>. Just make sure you call values() to get back to a List<SObject> which you can operate on.

Map<Id, SObject> uniqueRecords = new Map<Id, SObject>(contactsToSend);
update uniqueRecords.values();

You must log in to answer this question.

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