Friday, February 13, 2009

AllColumns() considered harmful

It looks tempting to use AllColumns when using CRM QueryExpression or QueryByAttribute, rather than building a ColumnSet that includes only the columns you want. However, I've found that some unexpected behaviour (to me at least) may occur if you attempt to update entities retrieved using AllColumns.
It appears that if you include AllColumns() and then do an update, the Update command applies an update to ALL attributes, even if you only change a single field in your code. If you do not change a particular field in code, Update appears to try to update the field to its original value, which causes no change to that field.
A problem arises if the entity being updated is in a parental relationship with other entities, with a Cascade/Assign (the default), and those other entities have different owners to that of the parent object.
The Update command apparently causes the ownerid to be updated (to the same value), and this then causes a cascading assignment of ownership to the child object, setting all of their ownerships to that of the parent object.
Not good, for example, if you have tasks related to a given opportunity via a parental relationship with default (Cascade/Assign) behaviour, all assigned to different people, and you then do an update with AllColumns to that opportunity, only changing an opportunity field unrelated to the ownership in your code.
The tasks will end up being reassigned to the owner of the opportunity because
the AllColumns update makes CRM think the ownerid has been altered and then it triggers the parental relationship's cascading assignment .
This behaviour is not explicitly documented (or if it is, I couldn't find it) and it took me quite a while to work out what was going on.