What if you had to synchronize access to Dynamics data from the external applications/components. Maybe there is a scheduled process that’s scheduled to run nightly on different servers, and that’s supposed to process that data, or maybe there is a multithreaded application that’s using multiple threads.. Whatever the case is, imagine that you need to ensure that those different processes/threads do not start processing the same data in parallel.
You might think of some solution that involves external synchronization, but, to make things simple, you could just rely on Dynamics itself for this.
When registering a plugin, we can choose a stage, and, depending on the stage, the plugin might run in a database transaction. If we choose a stage where the plugin runs in a transaction, we can use such a plugin to update some kind of a well-known record in Dynamics. Since it’ll be happening in transaction, once the plugin starts, it will lock the record. So the second instance of the same plugin, which will be running in another transaction, will be locked out until the first transaction has finished.
That’s the theory, but plugins are more for server-side processing, and I started this post by describing an external application scenario.
This is where we can use a custom action:
For example, imagine an entity that’s maintaining a queue entity id-s that your external app needs to process. You may have many instances of that app running on different servers, for instance, and, by using this approach, you can ensure that the same queued item is not processed twice. Most of the processing will still be happening in parallel, and the only time it will be sequential is when those applications will be querying the custom action to retrieve next data id.
Now, what is that Well-Known record on the diagram? It does not matter really – it can be any record that’s always there. You might create a custom entity for that if you wanted to. Or you might use a dedicated account record..
Basically, all you need to do at the start of the plugin is this:
var entity = new Entity(“account”);
entity.Id = Guid.Parse(“…”);//Use that record’s id
Or you might use a query to find that account.. Or you might use a dedicated custom entity. As soon as your plugin is registered in the PostOperation, this will be happening in transaction. So no two plugins will be able to do this at the same time – they’ll be doing it sequentially.
Then you can use another query to find data id and pass it back to the custom action output parameters through plugin context:
context.OutputParameters[“dataid”] = …
Last but not least, you may want to mark the records with that dataid is “processed” somehow (using statusreason.. or a dedicated field.. or somehow else), just so you the next call to the same custom action does not produce the same dataid as a result.
Then, register the plugin on your custom action message, in the post operation, and that’s about it.
As for calling the custom action from C#, here is a basic exampe:
OrganizationRequest request = new OrganizationRequest(“actionname”);
OrganizationResponse response = service.Execute(request);
var op1 = (string)response.Results[“dataid”];//string output parameter