As we know that set<Sobject>
and list<Sobject>
are collection type.
So basic question I do have why Set doesn't support DML operation ?
We can perform DML on List<Sobject>
but why not on set<Sobject>
Any idea?
As we know that set<Sobject>
and list<Sobject>
are collection type.
So basic question I do have why Set doesn't support DML operation ?
We can perform DML on List<Sobject>
but why not on set<Sobject>
Any idea?
One reason may be that Set<SObject>
is a risky mechanism to use: equality is based on all the fields (so is expensive) and if fields are changed logic can easily break. Same problem using SObject
as a Map
key. So not a pattern to be encouraged.
But perhaps just because also supporting Set<SObject>
adds a bunch of extra methods that need documenting and supporting. (Given that there isn't any common superclass.) And the conversion to list is trivial:
Set<SObject> s = ...;
someDmlOperation(new List<SObject>(s));
Set
equality for objects (including SObjects
) being added to a set (to determine if it already exists in the set or not) is actually based on a hash, rather than a literal comparison of every field, which means it's ludicrously fast (~0.010189 CPU limit per .add()
vs ~0.011671 CPU limit per result = sObject1 == sObject2;
). Still, your point about the risks of Set<SObject>
is good.
.add()
-ing all 644 records, 1000 times (total of 644,000 calls to .add()
) came to 11552 CPU time / 11999 ms for all 102 fields, and 3374 CPU time / 3437 ms for the single field. That comes to 0.017938 CPU time / 0.018632 ms (i.e. 18 us) per record with all 102 fields vs 0.05239 CPU time / 0.005337 ms (5 us) per record with a single field. Growth appears to be linear at ~0.3 us per additional field.
Sets (and Maps) cannot be cast to Sets of a different type. For example, Set<sObject> t = (Set<sObject>)new Set<Contact>()
will fail with the message Incompatible types since an instance of Set<Contact> is never an instance of Set<SObject>
. The database methods, and presumably DML keywords, are not implemented as generic methods, so they could only take a Set<sObject>
, not any concrete sObject type. That would be a radical departure from the behavior of the List
overloads, which can take either a List<sObject>
or e.g. a List<Contact>
, because lists are implicitly convertible from a contained type to a superclass of that contained type.
Most likely, the methods were not implemented as generics just because it would make the syntax awkward, since you would need something like insert<Contact> new Set<Contact>()
, or they would need to add special compiler logic to deduce the type of the passed object. The actual upside is pretty minor as well, as Keith C's answer explains, since Set<sObject>
can have behavior that is surprising to developers, and converting it to a list is relatively minor.
The values inside a set are supposed to be immutable; changing them means that values can be "lost" inside the object until the next time you debug the object, which seems to reset its internal state. In other words, it could introduce all kinds of subtle bugs, particularly on insert/upsert operations.