恰好创建了 33 条记录后插件执行停止,原因是什么?

Plugin Execution Halts After exactly 33 records created, What is the cause?

我有一个插件可以在名为 "Alter Unit Order" 的实体中创建记录。它应该为从合同开始日期到合同结束日期的每一天创建记录。无论如何,该插件只会创建 33 条记录。我认为这可能是因为进行了多少 FetchXML 查询。如果是这样,修复方法是什么?

这里是插件的代码:

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;

                }
            }
        }
    }


}

是的,我明白了。 foreach 循环是 运行 每次迭代查询 3 次。每次迭代都会创建一条记录。 33 次迭代的 3 次查询是 99 次查询。加上 foreach 循环之前的 1 个 fetchxml 查询,总共有 100 个查询。 Microsoft 对每条消息有 100 个查询的服务器端限制。这就是为什么我每次只创建 33 条记录。