function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
DavidHabib.ax407DavidHabib.ax407 

How Sets handle sObjects

I was using a set of sObjects, assuming that the set would prevent me from putting the same sObject in the set multiple times.  Unfortunately, I found that if I modified one of the fields of the sObject between additions to the set, then the sObject would get put on multiple times.  Is this expected behavior or a bug?

 

Here is a sample test routine which asserts, exposing the problem:

 

    static testmethod void SetSobjectBug() {
        Account acc = new Account(name='Individual');
        insert acc;
        Contact con = new Contact(Lastname='Testy', AccountId=acc.Id);
        insert con;
        Campaign cmp = new Campaign(name='Test Campaign');
        insert cmp;
        CampaignMember cm = new CampaignMember(CampaignId=cmp.Id, ContactId=con.Id, Status='Sent');
        
        Set<CampaignMember> setCM = new Set<CampaignMember>();
        system.assert(setCM.add(cm));
        cm.Status = 'Responded';
        system.assert(setCM.add(cm) == false);  // THIS ASSERTS.  If cm.Status is not changed, it won't assert.
    }

 

I was assuming the set was holding onto a reference to the object, but given this assert, I wonder if the set is make a full copy of the object, and doing a full compare to test membership?

 

Thanks,
Dave

jhurstjhurst

Dave,

 

The Set should actually create a full copy.  The Documentation does describe what you are seeing:

 

"Uniqueness of sObjects is determined by comparing fields. For example, if you try to add two accounts with the same name to a set, only one is added.  However, if you add a description to one of the accounts, it is considered unique."

 

So, since you have two different records (with different statuses) they are both added.  

 

Also, the ID field is the primary key for the record.  If you change your code to:

 

 

    static testmethod void SetSobjectBug() {
        Account acc = new Account(name='Individual');
        insert acc;
        Contact con = new Contact(Lastname='Testy', AccountId=acc.Id);
        insert con;
        Campaign cmp = new Campaign(name='Test Campaign');
        insert cmp;
        CampaignMember cm = new CampaignMember(CampaignId=cmp.Id, ContactId=con.Id, Status='Sent');
        insert cmp;
        Set<CampaignMember> setCM = new Set<CampaignMember>();
        system.assert(setCM.add(cm));
        cm.Status = 'Responded';
        system.assert(setCM.add(cm) == false);  // THIS ASSERTS.  If cm.Status is not changed, it won't assert.
    }

 Then the assertion will fail, because you are trying to add the same CampaignMember (with the same ID) to the set.

 

Hope this helps.

 

Jay

 

DavidHabib.ax407DavidHabib.ax407

Thanks for clarifying Jay.  Your quote from the documentation was what I was looking for, but didn't find.  I knew my sample code was incorrect.  I was just trying to duplicate the issue I ran into.

 

Thanks,

Dave