3
votes

I'm trying to make a custom workflow on Dynamics CRM. I need to delete some entities when another entity is deleted.

I created my class library and I retrieved the Guid of the deleted entity with this code:

    protected override void Execute(CodeActivityContext executionContext)
    {
        ITracingService tracingService = executionContext.GetExtension<ITracingService>();

        IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
        IOrganizationServiceFactory serviceFactory =
            executionContext.GetExtension<IOrganizationServiceFactory>();
        IOrganizationService service =
            serviceFactory.CreateOrganizationService(context.UserId);

        mService = service;
        mExecutionContext = executionContext;

        Guid myTipologyTypeDeleted = context.PrimaryEntityId;
        bool isReading = context.PrimaryEntityName.Equals(new_tipologialettura_richiesta.EntityLogicalName);
        bool isMaintenance = context.PrimaryEntityName.Equals(new_tipologiamanutenzionerichiesta.EntityLogicalName);

        bool myResult = AddOnIntervention(isReading, isMaintenance, myTipologyTypeDeleted);


        // Retrieve the summands and perform addition
        result.Set(executionContext, myResult);
    }

And here all works, I get the Guid and I get the type (reading or maintenance).

My problem is when I try to retrieve the entity with this code (the same code is working perfectly in another workflow started on record creation, but on record delete gives me error).

            Entity myReadingEntity = mService.Retrieve(new_tipologialettura_richiesta.EntityLogicalName, myTipologyTypeDeleted, new ColumnSet(true));

Here I get an exception saying that no record of type MyType with id myId has been found.

I checked the record and it still exist in the DB so it has not been deleted. What I'm doing wrong?

Thanks

1
1) If you're trying to delete child records of the record that is being deleted, have you considered changing the relationship properties to automatically delete the records for you? 2) That retrieve call that's failing...are you trying to retrieve the record that's currently being deleted? Do you need to retrieve it so that you can inspect values on it? 3) You say you checked the db for the record and it still exists, when are you doing that check? If you're checking after the workflow finishes running but the workflow failed, then the platform might have rolled back the delete operation. - Polshgiant
@Polshgiant thanks for replying! I reply here: 1) it's not child, only related by another workflow's operation. 2) I have two entityRef in this entity which refers to two entities I need in my operations, how can I retrieve the entire record without failing? 3) probably yes, it was a rollback as you said - Pier Giorgio Misley
I would expect the platform would let you retrieve the record that's currently being deleted, but if not then you could have your custom wf assembly accept more input parameters and then in the wf designer you could pass in values from the record that's being deleted. Does that make sense? - Polshgiant
When does this workflow run? Pre, Post, or Async. Also, why is this being done in a workflow instead of a plugin? - Nicknow

1 Answers

1
votes

I think the best thing to write your custom logic here will be a Plugin, You Should write a plugin that runs on the

Message: Delete
Stage:    POST

After registering the plugin on Post Delete Operation, you should add an pre-image that will be available on Post Delete with all the attributes.Instead of issuing a retrieve, the best practice is to push the required data in an image instead.

Taken from MSDN: Registering for pre or post images to access entity attribute values results in improved plug-in performance as compared to obtaining entity attributes in plug-in code through RetrieveRequest or RetrieveMultipleRequest requests.

In your plugin change the lines of code:

Entity myReadingEntity = mService.Retrieve(new_tipologialettura_richiesta.EntityLogicalName, myTipologyTypeDeleted, new ColumnSet(true));

to

if (context.PreEntityImages.Contains("YourImageName"))
{
  Entity myReadingEntity = context.PreEntityImages["YourImageName"]
}