Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Customer experience | Sales, Customer Insights,...
Answered

Custom workflow activity does not see the expected counts of the records it queries for

(0) ShareShare
ReportReport
Posted on by 1,581

I have Entity A and Entity B related via 1:N. 

There will usually be 1 or more Entity B records hanging off of a particular Entity A record. 

Every time I deactivate an Entity B record, I need a workflow to run that checks and counts the number of inactive Entity B records related to the same Entity A that the deactivated Entity B record that was just deactivated.

The workflow should also check and count the number of Active Entity B records related to entity A. 

Once it has the counts, there are other steps in the workflow that perform a number of operations on a number of things based on those counts. 

The problem is the counts are not coming back correctly. 

To do the actual counts, I use the following fetch xml query - which searches for and counts the number of inactive related records that hang off the same Entity A parent via 1:N relationship. 

  
    
    
    
    
    
    
    
    
    
      
    
    
      
      
        
      
    
  

The other etch xml query searches for active related records that hang a 1:N relationship

  
    
    
    
    
    
    
    
    
    
      
    
    
      
      
        
      
    
  

When running inside the custom workflow activity, the data returned is errant. I get 0 active and 0 inactive which is wrong.

In the example I am using here, after deactivating an Entity B child and since this particular parent has only that child record on it, the expected result is 0 active and 1 inactive.

I get that result if I use fetchxml via xrmtoolbox, but not in the custom workflow activity. 

Everything is working except for the active and inactive counts. 

In the screen shot below, when I deactivated the child record, the custom workflow activity should run and see that there is 0 active and 1 inactive but it does not. It sees 0 active and 0 inactive. 

Screen-Shot-2021_2D00_03_2D00_10-at-11.19.49-PM.png

I have some trace-logging enabled and this is what is in the log.

Custom Workflow Activity Started.
User ID: 009284ef-7b36-e811-a972-000d3a1a7a9b
Primary Entity ID: 2be5642b-6e7c-eb11-a812-000d3a8bd140
Primary Entity Name: cpp_transfercriteria
URL parser completed successfully
At End of Main CodeActivityContext.
Inactive Count: 0
Active Count: 0

What on earth am I missing that the Inactive count is not 1 when there is clearly one inactive child record?

I've included the custom workflow activity code below.  Any help would be greatly appreciated. 

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading.Tasks;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using System.Runtime.Serialization;
using Microsoft.Xrm.Sdk.Query;

namespace ACECountRecordsWKF
{
    public abstract class ACECountRecordsWKF : CodeActivity
    {

        public sealed class LocalWorkflowContext
        {
            internal IServiceProvider ServiceProvider
            {
                get;

                private set;
            }

            internal IOrganizationService OrganizationService
            {
                get;

                private set;
            }

            internal IWorkflowContext WorkflowExecutionContext
            {
                get;

                private set;
            }

            internal ITracingService TracingService
            {
                get;

                private set;
            }

            private LocalWorkflowContext()
            {
            }

            internal LocalWorkflowContext(CodeActivityContext executionContext)
            {
                if (executionContext == null)
                {
                    throw new ArgumentNullException("serviceProvider");
                }

                // Obtain the execution context service from the service provider.
                this.WorkflowExecutionContext = (IWorkflowContext)executionContext.GetExtension();

                // Obtain the tracing service from the service provider.
                this.TracingService = (ITracingService)executionContext.GetExtension();

                // Obtain the Organization Service factory service from the service provider
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)executionContext.GetExtension();

                // Use the factory to generate the Organization Service.
                this.OrganizationService = factory.CreateOrganizationService(this.WorkflowExecutionContext.UserId);
            }

            internal void Trace(string message)
            {
                if (string.IsNullOrWhiteSpace(message) || this.TracingService == null)
                {
                    return;
                }

                if (this.WorkflowExecutionContext == null)
                {
                    this.TracingService.Trace(message);
                }
                else
                {
                    this.TracingService.Trace(
                        "{0}, Correlation Id: {1}, Initiating User: {2}",
                        message,
                        this.WorkflowExecutionContext.CorrelationId,
                        this.WorkflowExecutionContext.InitiatingUserId);
                }
            }
        }
    }

    public abstract class FetchWF : CodeActivity
    {
        protected FetchExpression ActiveRecordQuery;
        protected FetchExpression InactiveRecordQuery;
        protected IOrganizationService service;
        protected override void Execute(CodeActivityContext executionContext)
        {   ITracingService tracingService = executionContext.GetExtension();
            tracingService.Trace("Custom Workflow Activity Started.");
            if (executionContext == null)
            {
                throw new ArgumentNullException("serviceProvider");
            }

            // Construct the Local plug-in context.
            var context = executionContext.GetExtension();
            var servicefactory = executionContext.GetExtension();
            service = servicefactory.CreateOrganizationService(context.UserId);
            tracingService.Trace("User ID: "   context.UserId);
            var CurrentEntityID = context.PrimaryEntityId;
            tracingService.Trace("Primary Entity ID: "   context.PrimaryEntityId);
            var entityLogicalName = context.PrimaryEntityName;
            tracingService.Trace("Primary Entity Name: "   context.PrimaryEntityName);

            //var userId = context.InitiatingUserId;
            var entityReference = new DynamicUrlParser(RecordUrl.Get(executionContext));

            tracingService.Trace("URL parser completed successfully");

            string fetchActive = QueryForActiveRecords.Get(executionContext);
            fetchActive = String.Format(fetchActive, entityReference.ToString());
            ActiveRecordQuery = new FetchExpression(fetchActive);

            string fetchInActive = QueryForInactiveRecords.Get(executionContext);
            fetchInActive = String.Format(fetchInActive, entityReference.ToString());
            InactiveRecordQuery = new FetchExpression(fetchInActive);

            tracingService.Trace("At End of Main CodeActivityContext.");
        }

        [Input("Record Dynamic Url")]
        [RequiredArgument]
        public InArgument RecordUrl { get; set; }

        [Input("QueryForActiveRecords")]
        public InArgument QueryForActiveRecords { get; set; }

        [Input("QueryForInactiveRecords")]
        public InArgument QueryForInactiveRecords { get; set; }

    }


    public class FetchWFCountResult : FetchWF
    {
        protected override void Execute(CodeActivityContext executionContext)
        {
            ITracingService tracingService = executionContext.GetExtension();

            base.Execute(executionContext);

            var x = service.RetrieveMultiple(InactiveRecordQuery).Entities.Count;
            tracingService.Trace("Inactivae Count: "   x);

            var y = service.RetrieveMultiple(ActiveRecordQuery).Entities.Count;
            tracingService.Trace("Acctivae Count: "   y);

            if (service.RetrieveMultiple(InactiveRecordQuery).Entities.Count > 0)
            {
                tracingService.Trace("Inside top level if where Inactive Record Query Count > 0");
                InactiveRecordCount.Set(executionContext, service.RetrieveMultiple(InactiveRecordQuery).Entities.Count);

                if (service.RetrieveMultiple(ActiveRecordQuery).Entities.Count > 0)
                {
                    tracingService.Trace("Inside Mid level if where Active Record Query Count > 0");
                    tracingService.Trace("ActiveRecordCount Value is: "   service.RetrieveMultiple(ActiveRecordQuery).Entities.Count);
                    ActiveRecordCount.Set(executionContext, service.RetrieveMultiple(ActiveRecordQuery).Entities.Count);

                }
               
            }
            else {
                ActiveRecordCount.Set(executionContext, 0);
                tracingService.Trace("Set Default ActiveRecordCount to 0.");
                InactiveRecordCount.Set(executionContext, 0);
                tracingService.Trace("Set Default InactiveRecordCount to 0.");

            }
        }

        [Output("ActiveRecordCount")]
        public OutArgument ActiveRecordCount { get; set; }

        [Output("InactiveRecordCount")]
        public OutArgument InactiveRecordCount { get; set; }

    }

  • ACECORP Profile Picture
    ACECORP 1,581 on at
    RE: Custom workflow activity does not see the expected counts of the records it queries for

    Making it asynchronous causes it to report the correct number of Inactive and Active records which is different than what happens when it runs synchronously.  

    Isn't a synchronous workflow supposed to operate the same as a post-operation/post-image plugin regarding how it considers the values of the fields that the workflow is actually setting?

    Why would it matter that it is asynchronous as opposed to synchronous?

    The workflow itself is setting the status code to from 0 to 1 and since the workflow itself is setting this, why doesn't the next step in that same workflow see the fact the value is now 1?

    The suggestion to make it asynchronous fixed the issue, but I don't understand why it fixed the issue given the same workflow is setting the value in a previous step, and the expectation is that the next step in the same workflow would see the new value given the nature of how workflows operate. 

  • ACECORP Profile Picture
    ACECORP 1,581 on at
    RE: Custom workflow activity does not see the expected counts of the records it queries for

    It does start “after” as you suggested and I already posted the trace logs above showing that it’s getting 0 for both values.

    I’ll try setting it to asynchronous instead of real time but I can’t imagine what difference that would make.

  • sardar ahmed Profile Picture
    sardar ahmed 520 on at
    RE: Custom workflow activity does not see the expected counts of the records it queries for

    Hi,

    There seems to be no issue with the fetchxmls , probably, you should put some trace logs in your custom workflow and check if the values are passed as expected.

  • Verified answer
    ChangeFrenzoId Profile Picture
    ChangeFrenzoId 465 on at
    RE: Custom workflow activity does not see the expected counts of the records it queries for

    Hi Jim,

    Can you please:

    • Make sure that WF is configured "Start when : AFTER", like below:
      pastedimage1615446542270v1.png
    • Try to update the WF and make it async (background), and observe the trace

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Vahid Ghafarpour – Community Spotlight

We are excited to recognize Vahid Ghafarpour as our February 2025 Community…

Tip: Become a User Group leader!

Join the ranks of valued community UG leaders

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 292,494 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 231,305 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans