As I have recently mentioned, the possibilities of defining cascade deletes in Microsoft Dynamics CRM 2011 are quite limited. Only one parent entity can have the relationship behavior set to Cascade Delete. When you create a manual intersect entity to connect two or more other entities, this constraint is simply not acceptable for the end users.
Consider this classic scenario:
Instead of just associating contacts with a parent account, you want to be able to define a more dynamic model.This could be accomplished using Connections and Connection Roles, but that too has a number of pros and cons, which I will not go into in this article.
When creating the relations to the Role entity, only one of them (i.e. either the relation to Account, Contact or Function) can be defined with cascade delete. What you would like here is to specify Cascade for both Account and Contact, and Remove Link for Function.
When using a manual intersect entity as in this example, the Role object will loose all meaning if either the associated Contact or the associated Account is deleted, thus the Role should of course be deleted in both cases.
To solve this, I will create a plugin which can be configured to perform the cascade behavior where it is not possible to do it by customizations only.
First a few notes about the different types of relationship behavior during delete.
The Restrict behavior verifies if there are any existing associating records before stage 20 (Pre Operation). So this behavior cannot be used, as we want to perform our configured plugin delete within the triggering transaction to ensure proper rollback behavior.
The Cascade behavior can only be defined for one relationship, which in this case will be to the Contact entity.
The Remove Link behavior will leave the child records in CRM, which is possible as the relationship attribute will be nulled by CRM between stage 10 and 20. Using this behavior alone would leave Roles defining e.g. that "Jonas has function Consultant at company null" when deleting accounts.
A plugin shall delete children of a parent record that is being deleted.
To specify which relationships that shall invoke this function, I use a configuration entity in CRM. It is also possible to pass the configuration as parameters to the plugin constructor, but then you have to enter the configuration in the step registrations, which is not very user friendly to the sysadmin.
The operation shall be performed in stage 20 (Pre Operation) as it will then be within the transaction of the triggering delete, and the children will be deleted before the parent record is actually removed from the database.
As the lookup attributes are nulled before stage 20 of the event execution pipeline, the plugin will retrieve a list of the children to delete in stage 10. This list is passed to the plugin triggered in stage 20 within the context's SharedVariables.
To improve performance, a cache of Cascade Delete configurations is maintained in the plugin class. If a configuration record is created, updated or deleted, the cache will be cleared.
In the next post I demonstrate and explain the code in the plugin, and also provide a complete solution for deploying multiple cascade delete in your Microsoft Dynamics CRM. Stay tuned!
Labels: Community, Customization, Plugin