3

I have a plugin that creates records in an entity called "Alter Unit Order". It is supposed to create records for each day from contract start date to contract end date. No matter what, the plugin will only create 33 records. I'm thinking its probably because of how many FetchXML queries are being made. If so, what is the fix?

Here the code for the plugin:

using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Plugins;

/// <summary>
/// This plugin takes the data provided in the contract lines and makes Unit Orders.. 
/// Inside the unit orders, an Alter Unit Orders table is present.
/// The Alter Unit Orders table describes the daily order for each day in the contract's duration. 
/// </summary>

namespace DCWIMS.Plugins
{
    [CrmPluginRegistration(MessageNameEnum.Update,
    "contract",
    StageEnum.PostOperation,
    ExecutionModeEnum.Asynchronous,
    "statecode",
    "Post-Update Contract",
    1000,
    IsolationModeEnum.Sandbox,
    Image1Name = "PreImage",
    Image1Type = ImageTypeEnum.PreImage,
    Image1Attributes = "")]
    public class UnitPlugin : IPlugin
    {

        public void Execute(IServiceProvider serviceProvider)
        {
            // Extract the tracing service for use in debugging sandboxed plug-ins.
            // Will be registering this plugin, thus will need to add tracing service related code.
            ITracingService tracing = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


            //obtain execution context from service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)
                serviceProvider.GetService(typeof(IPluginExecutionContext));


            // The InputParameters collection contains all the data passed in the message request.
            if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
            {

                //obtain the target entity from the input parameters.
                Entity entity = (Entity)context.InputParameters["Target"];

                //Get the before image of the updated contract
                Entity PreImage = context.PreEntityImages["PreImage"];

                //verify that the target entity represents the the contract entity and contract is Active (statecode 2)
                if (entity.LogicalName != "contract" || entity.GetAttributeValue<OptionSetValue>("statecode").Value != 2)
                    return;


                //Redundancy to prevent execution when going from Hold/cancel to active
                if (PreImage.GetAttributeValue<OptionSetValue>("statecode").Value == 3 || entity.Contains("cancelon"))
                    return;


                //obtain the organization service for web service calls.
                IOrganizationServiceFactory serviceFactory =
                        (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

                //This will be used as service for web service calls
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);


                //Core Plugin Code in try block 

                try
                {

                    //Get Contract StartDate                   
                    DateTime startDate = (DateTime)PreImage["activeon"];

                    //Get Contract EndDate
                    DateTime endDate = (DateTime)PreImage["expireson"];

                    //Create an instance of the range class
                    Eachday range = new Eachday();

                    //use Weekday method of range class to get a weekdays list
                    var weekdays = range.WeekDay(startDate, endDate);                               

                    //Get Contract Number
                    string contractNumber = (string)PreImage["contractnumber"];


                    //Get Unit Order Lookup Id
                    EntityReference unitOrder = (EntityReference)PreImage.Attributes["new_unitorderid"];
                    var unitOrderId = unitOrder.Id;


                    //Query for the different Location Destinations and Serving Groups
                    string fetch = @"  <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
                        <entity name='contractdetail'>
                            <attribute name='new_servinggroup' alias='serving' />
                            <attribute name='new_locationdestination' />
                            <filter type='and'>
                                <condition attribute='new_locationdestination' operator='not-null' />
                            </filter>
                            <link-entity name='contract' from='contractid' to='contractid' alias='ad'>
                                <filter type='and'>
                                    <condition attribute='contractnumber' operator='eq' value='" + contractNumber + @"' />
                                </filter>
                            </link-entity>
                        </entity>
                    </fetch>";

                    //Put fetch result into an entity collection
                    EntityCollection result =
                        service.RetrieveMultiple(new FetchExpression(fetch));


                    //iterate through entire contract duration and create the records
                    foreach (var day in weekdays)
                    {
                        var currentday = day.Split(',')[0];

                        //Create a record for each Serving Group and Destination pair
                        foreach (var ent in result.Entities)
                        {
                            //Get the Serving Group
                            AliasedValue aliasedValue = ent.GetAttributeValue<AliasedValue>("serving");
                            object aliasValue = aliasedValue.Value;
                            OptionSetValue optionset = (OptionSetValue)aliasValue;
                            int group = optionset.Value;

                            //Get the location destination
                            var location = ent.GetAttributeValue<string>("new_locationdestination");

                            //Create the record and fill the attributes
                            Entity alterunit = new Entity("new_alterunitorder");
                            alterunit.Attributes.Add("new_orderdate", DateTime.Parse(day));
                            alterunit.Attributes.Add("new_name", contractNumber);
                            alterunit.Attributes["new_orderlineid"] =
                                new EntityReference("new_units", unitOrderId);
                            var selection = new OptionSetValue(group);
                            alterunit.Attributes["new_servinggroup"] = selection;
                            alterunit.Attributes.Add("new_location", location);

                            //use Fetch Query here and feed the switch below
                            //Fetch AM SUM for the current serving group and location
                            string fetch_am = @" <fetch aggregate = 'true' distinct = 'false' >
                                <entity name = 'contractdetail' >
                                    <attribute name = 'new_mondayunits' alias = 'new_mondayunits_sum' aggregate = 'sum' />
                                    <attribute name = 'new_tuesdayunits' alias = 'new_tuesdayunits_sum' aggregate = 'sum' />     
                                    <attribute name = 'new_unitswednesday' alias = 'new_unitswednesday_sum' aggregate = 'sum' />
                                    <attribute name = 'new_unitsthursday' alias = 'new_unitsthursday_sum' aggregate = 'sum' />   
                                    <attribute name = 'new_unitsfriday' alias = 'new_unitsfriday_sum' aggregate = 'sum' />                          
                                    <filter type='and' >
                                        <condition value= '100000001' attribute = 'new_servingtime' operator = 'eq' />
                                        <condition value = '" + group + @"' attribute = 'new_servinggroup' operator= 'eq' />
                                        <condition value = '" + location + @"' attribute = 'new_locationdestination' operator= 'eq' />
                                        <condition value = '0' attribute = 'statecode' operator= 'eq' />
                                    </filter >
                                    <link-entity name = 'contract' from = 'contractid' to = 'contractid' alias = 'aa'>
                                        <filter type = 'and' >                         
                                            <condition attribute = 'contractnumber' operator= 'eq' value = '" + contractNumber + @"' />
                                        </filter >
                                    </link-entity >   
                                </entity >
                            </fetch > ";

                            var fetch_one = new FetchQuery(fetch_am);
                            var am_list = fetch_one.Result(serviceProvider);

                            //Fetch LUNCH SUM for the current serving group and location
                            string fetch_lunch = @" <fetch aggregate = 'true' distinct = 'false' >
                                <entity name = 'contractdetail' >
                                    <attribute name = 'new_mondayunits' alias = 'new_mondayunits_sum' aggregate = 'sum' />
                                    <attribute name = 'new_tuesdayunits' alias = 'new_tuesdayunits_sum' aggregate = 'sum' />     
                                    <attribute name = 'new_unitswednesday' alias = 'new_unitswednesday_sum' aggregate = 'sum' />
                                    <attribute name = 'new_unitsthursday' alias = 'new_unitsthursday_sum' aggregate = 'sum' />   
                                    <attribute name = 'new_unitsfriday' alias = 'new_unitsfriday_sum' aggregate = 'sum' />                          
                                    <filter type='and' >
                                        <condition value= '100000002' attribute = 'new_servingtime' operator = 'eq' />
                                        <condition value = '" + group + @"' attribute = 'new_servinggroup' operator= 'eq' />
                                        <condition value = '" + location + @"' attribute = 'new_locationdestination' operator= 'eq' />
                                        <condition value = '0' attribute = 'statecode' operator= 'eq' />
                                    </filter >
                                    <link-entity name = 'contract' from = 'contractid' to = 'contractid' alias = 'aa'>
                                        <filter type = 'and' >                         
                                            <condition attribute = 'contractnumber' operator= 'eq' value = '" + contractNumber + @"' />
                                        </filter >
                                    </link-entity >   
                                </entity >
                            </fetch >";

                            var fetch_two = new FetchQuery(fetch_lunch);
                            var lunch_list = fetch_two.Result(serviceProvider);

                            //Fetch PM SUM for the current Serving Group and location
                            string fetch_pm = @"    <fetch aggregate = 'true' distinct = 'false' >
                                <entity name = 'contractdetail' >
                                    <attribute name = 'new_mondayunits' alias = 'new_mondayunits_sum' aggregate = 'sum' />
                                    <attribute name = 'new_tuesdayunits' alias = 'new_tuesdayunits_sum' aggregate = 'sum' />     
                                    <attribute name = 'new_unitswednesday' alias = 'new_unitswednesday_sum' aggregate = 'sum' />
                                    <attribute name = 'new_unitsthursday' alias = 'new_unitsthursday_sum' aggregate = 'sum' />   
                                    <attribute name = 'new_unitsfriday' alias = 'new_unitsfriday_sum' aggregate = 'sum' />                          
                                    <filter type='and' >
                                        <condition value= '100000003' attribute = 'new_servingtime' operator = 'eq' />
                                        <condition value = '" + group + @"' attribute = 'new_servinggroup' operator= 'eq' />
                                        <condition value = '" + location + @"' attribute = 'new_locationdestination' operator= 'eq' />
                                        <condition value = '0' attribute = 'statecode' operator= 'eq' />
                                    </filter >
                                    <link-entity name = 'contract' from = 'contractid' to = 'contractid' alias = 'aa'>
                                        <filter type = 'and' >                         
                                            <condition attribute = 'contractnumber' operator= 'eq' value = '" + contractNumber + @"' />
                                        </filter >
                                    </link-entity >   
                                </entity >
                            </fetch >";

                            var fetch_three = new FetchQuery(fetch_pm);
                            var pm_list = fetch_three.Result(serviceProvider);


                            switch (currentday)
                            {
                                case "Monday":
                                    alterunit.Attributes.Add("new_amsnack", am_list[0]);
                                    alterunit.Attributes.Add("new_lunch", lunch_list[0]);
                                    alterunit.Attributes.Add("new_pmsnack", pm_list[0]);
                                    break;

                                case "Tuesday":
                                    alterunit.Attributes.Add("new_amsnack", am_list[1]);
                                    alterunit.Attributes.Add("new_lunch", lunch_list[1]);
                                    alterunit.Attributes.Add("new_pmsnack", pm_list[1]);
                                    break;

                                case "Wednesday":
                                    alterunit.Attributes.Add("new_amsnack", am_list[2]);
                                    alterunit.Attributes.Add("new_lunch", lunch_list[2]);
                                    alterunit.Attributes.Add("new_pmsnack", pm_list[2]);
                                    break;

                                case "Thursday":
                                    alterunit.Attributes.Add("new_amsnack", am_list[3]);
                                    alterunit.Attributes.Add("new_lunch", lunch_list[3]);
                                    alterunit.Attributes.Add("new_pmsnack", pm_list[3]);
                                    break;

                                case "Friday":
                                    alterunit.Attributes.Add("new_amsnack", am_list[4]);
                                    alterunit.Attributes.Add("new_lunch", lunch_list[4]);
                                    alterunit.Attributes.Add("new_pmsnack", pm_list[4]);
                                    break;

                                default:
                                    Console.WriteLine($"An unexpected value ({currentday})");
                                    break;
                            }

                            service.Create(alterunit);


                        }
                    }



                }

                catch (FaultException<OrganizationServiceFault> ex)
                {
                    throw new InvalidPluginExecutionException("An error occured.. Phil is responsible.", ex);
                }

                catch (Exception ex)
                {
                    tracing.Trace("An Error Occured: {0}", ex.ToString());
                    throw;

                }
            }
        }
    }


}
Alan Judi
  • 1,074
  • 1
  • 16
  • 32
  • The same 33 records every time? Can you include some the Plugin Trace Log? There might be a simple explanation such as the 34th record has a null reference exception – jasonscript Aug 23 '18 at 01:05
  • no, its not the same 33 records. It creates a maximum of 33 records. I think its because in my foreach loop, I am running 3 queries. Before the foreach loop, there is one fetchxml query. Since each iteration of the loop creates a record, 33 records would equal 99 queries, plus 1 query prior to the loop. Meaning there is a limit of 100 queries per plugin execution, right?! – Alan Judi Aug 23 '18 at 13:13

1 Answers1

4

Yeah I figured it out. The foreach loop is running a query 3 times with each iteration. Each iteration creates a record. 3 queries for 33 iterations is 99 queries. Plus 1 fetchxml query prior to the foreach loop comes to a total of 100 queries. Microsoft has a server-side restriction of 100 queries per message. This is why I am only getting 33 records created each time.

Alan Judi
  • 1,074
  • 1
  • 16
  • 32